目录
cookie和session
cookie和session
- cookie
- 服务端保存在客户浏览器上的信息都可以称为cookie
- cookie的表现形式是以键值对的形式,可以有很多对
- 作用是网站用来辨别用户身份
- session
- session是存储在服务端上的信息
- session的表现形式也是键值对
- 总结
- cookie就是保存在客户端上的信息
- session就是保存在服务端上的信息
- session是基于cookie工作的(大部分的保存用户状态的操作都需要用到cookie)
cookie使用
cookie操作
- 尽管cookie是服务端告诉客户端浏览器需要保存内容,但是客户端浏览器也可以选择拒绝保存,
如果禁止了只要是需要记录用户状态的网站登录功能都无法使用了
- django中cookie的设置
- set_cookie()
- 在视图函数中,要返回一个HttpResponse对象,render,redirect的本质也是返回HttpResponse对象
- 如果我们要设置cookie,必须要先实例化一个对象,再给这个对象设置cookie
- 例如:
http_response_obj = HttpResponse()
http_response_obj.set_cookie(key, value)
return http_response_obj
- django获取cookie
- request.COOKIES
- cookie的其他操作
- 设置超时时间
- max_age
- expires 用于IE浏览器
http_response_obj.set_cookie(key, value, max_age=5, expires=5)
- 超过该时长cookie失效
- max_age和expires单位是秒
- 主动删除cookie
- http_response_obj.delete_cookie(key)
- 注销功能
cookie使用案例:实现一个简单登陆功能
- 用cookie来保存用户的登陆状态
- 在用户访问需要登陆的页面的时候,先定位到登陆页面,登陆成功后返回当前页面
- 注销
用户登陆状态保存
1. 登陆页面的视图函数及视图
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'wcy' and password == '123456':
return redirect('/home/')
return render(request, 'login.html')
<form action="" method="post">
<p>账号:<input type="text" name="username"></p>
<p>密码:<input type="text" name="password"></p>
<input type="submit">
</form
2.登陆成功后默认返回一个home页面
def home(request):
return HttpResponse('home页面,登陆成功默认跳转的页面')
可以发现一个问题,当我们登陆成功后会跳转到home页面,但是如果直接访问home页面也能够直接访问,不符合我们的登陆逻辑,那么接下来就要使用cookie来保存用户的登陆信息。
要使用cookie,我们就要先实例化对象,然后使用对象来添加cookie,接下来将我们的登陆的视图函数改成如下:
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'wcy' and password == '123456':
http_response_obj = redirect('/home/') # 实例化
http_response_obj.set_cookie('is_login', 'yes') # 添加cookie
return http_response_obj
return render(request, 'login.html')
此时登陆后我们查看页面的cookie会发现我们添加的cookie存在,但是我们只是添加了cookie,并没有使用它,接下来我们去home函数中判读cookie.
home函数中的判断如下:
当cookie验证成功时进入home页面,否则继续返回登陆页面
def home(request):
if request.COOKIES.get('is_login') == 'yes':
return HttpResponse('home页面,登陆成功默认跳转的页面')
return redirect('/login/')
至此,我们实现了登陆单个页面的cookie功能,我们需要在页面中判断cookie是否正确,那么当我们有许多个页面需要登陆才能访问呢?我们难道也要在对应的视图函数里一个一个的判断cookie吗,显然是吃力不讨好的,那么我们就可以写一个装饰器来判断cookie,这样只需要使用装饰器判断即可。
首先我们再添加几个页面
def page_a(request):
return HttpResponse('a页面,登陆成功才能访问的页面')
def page_b(request):
return HttpResponse('b页面,登陆成功才能访问的页面')
def page_c(request):
return HttpResponse('c页面,登陆成功才能访问的页面')
然后我们写一个函数装饰器来判断cookie
def login_auth(func):
"""
登陆状态判断
"""
def inner(request, *args, **kwargs):
if request.COOKIES.get('is_login') == 'yes':
res = func(request, *args, **kwargs)
return res
else:
return redirect('/login/')
return inner
然后只需要放在各个视图函数之前即可
@login_auth
def home(request):
# if request.COOKIES.get('is_login') == 'yes':
# return HttpResponse('home页面,登陆成功默认跳转的页面')
# return redirect('/login/')
return HttpResponse('home页面,登陆成功默认跳转的页面')
@login_auth
def page_a(request):
return HttpResponse('a页面,登陆成功才能访问的页面')
@login_auth
def page_b(request):
return HttpResponse('b页面,登陆成功才能访问的页面')
@login_auth
def page_c(request):
return HttpResponse('c页面,登陆成功才能访问的页面')
此时如果没有登录,访问上述页面都会定向到登陆页面,登陆成功之后才可以继续访问需要登陆的页面。
不过此时又有一个问题,当我们访问一个需要登陆的页面被重定向到登陆页面后,登陆成功后会自动的跳转到home页面而不是之前我们想要访问的页面,这是非常的不人性化的,所一接下来来解决这个问题。
定向到用户登陆之前访问的页面
首先我们要保存用户想访问的页面,登陆成功后再定向到之前访问的页面即可,我们需要在装饰器函数中更改逻辑。
首先将用户访问的页面地址保存,然后用next参数添加到定向的login页面后面
def login_auth(func):
"""
登陆状态判断
"""
def inner(request, *args, **kwargs):
user_visit_page = request.get_full_path() # 获取用户的访问地址
if request.COOKIES.get('is_login') == 'yes':
res = func(request, *args, **kwargs)
return res
else:
# 没有登陆时 定向到登陆页面 同时记录用户的访问地址
# 在login后加上一个参数next,记录用户的访问地址,然后在login函数中获取,再判断
return redirect('/login/?next={}'.format(user_visit_page))
return inner
然后在login函数中获取next中的值,登陆成功后重定向到用户最开始访问的页面
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'wcy' and password == '123456':
# 登陆成功后获取用户的访问地址,地址是存在next参数中
user_visit_url = request.GET.get('next')
if user_visit_url:
# 如果存在就定向到用户刚开始访问的这个地址
http_response_obj = redirect(user_visit_url)
else:
http_response_obj = redirect('/home/') # 实例化
http_response_obj.set_cookie('is_login', 'yes') # 添加cookie 无论定向到哪都要加cookie
return http_response_obj
return render(request, 'login.html')
最后实现了该功能
设置cookie超时参数
当用户长时间不登陆网站时,需要重新登陆,那么我们就可以设置一个超时时间,当超过这个时间后cookie会失效,用户需要重新登陆。
超时参数的设置非常简单,只要在set_cookie中添加一个参数max_age即可
# 添加cookie 无论定向到哪都要加cookie
# 5s后cookie失效
http_response_obj.set_cookie('is_login', 'yes', max_age=5)
IE浏览器中max_age要替换成expires参数才会生效
注销
注销只需要删除cookie即可
定义视图函数
@login_auth
def logout(request):
# 登陆成功才能注销,所以也要加装饰器判断
http_response_obj = redirect('/login/')
http_response_obj.delete_cookie('is_login')
return http_response_obj
然后登陆成功后访问logout页面即可注销,这里就不加按钮功能了
cookie的基本使用到此结束
session基本使用
session操作
- session数据是保存在服务端的,给客户返回的是一个随机字符串
格式: sessionid:随机字符串
- session数据在服务端是默认保存早数据库中的,可以指定其他的存储方法
- 默认情况下操作session需要用到django创建的表django_session
- 首先要执行数据库的迁移命令,创建默认的django_session表
- 设置session
request.session[key] = value
- 内部实现步骤
- django会自动生成随机字符串
- django自动将随机字符串存储到django_session表中
- 现在内存中产生操作数据的缓存
- 在相应结果的django中间件的时候才会真正的操作数据库
- 将产生的随机字符串发送给客户端浏览器保存
- 获取session
request.session.get(key)
- 内部实现步骤
- 从浏览器请求中获取sessionid对应的随机字符串
- 将获取到的随机字符串去django_session表中去比对
- 如果比对成功,则返回对应的数据并且封装到request.session中
- 如果比对失败,则request.session.get(key)返回的是None
- django中session默认的失效时间是14天,可以人为修改
- django_session表中的数据条数是取决于浏览器的
- 同一个计算机上同一个浏览器只会有一条记录
- 同一台计算机不同的浏览器也会有新的数据
- 当session过期的时候,同一台计算机同一个浏览器也肯有多条数据
- session的其他操作
- session可以当做字典来操作
- 批量添加session
- request.session[key1] = value1
- request.session[key2] = value2
- request.session[key4] = value3
- 上面已经说过,同一浏览器只有一条记录,所以无论添加多少条session,
表中都只有一条数据,但是我们可以获取到我们设置的所有session
- session设置过期时间
- request.session.set_expiry()
- 括号里可以放四种对象
- 整数:秒
- 日期对象:到期时间
- 0:关闭浏览器默认失效
- 不写:取决于django的全局session默认过期时间,默认是14天
- 读session的时候不会修改session的有效期,修改session的时候会重新设置session的有效期,会从修改的时间,重新计时。
- 清除session
- request.session.delete() # 只删服务端
- request.session.flush() # 浏览器和服务端全部清空
session版本的登陆
session版本的登陆和cookie版本的逻辑大致相同,只是将cookie的使用改成了session的使用
在使用session之前一定要记得数据库迁移命令,生成django_session表
视图函数部分
from django.shortcuts import render, HttpResponse, redirect, reverse
# Create your views here.
def login_auth(func):
"""
登陆状态判断
"""
def inner(request, *args, **kwargs):
user_visit_page = request.get_full_path() # 获取用户的访问地址
# print(request.session.get('is_login'))
if request.session.get('is_login') == 'yes':
res = func(request, *args, **kwargs)
return res
else:
# 没有登陆时 定向到登陆页面 同时记录用户的访问地址
# 在login后加上一个参数next,记录用户的访问地址,然后在login函数中获取,再判断
return redirect(reverse('login')+'?next={}'.format(user_visit_page))
return inner
def login(request):
if request.method == "POST":
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'wcy' and password == '123456':
user_visit_url = request.GET.get('next')
# 添加session
request.session['is_login'] = 'yes'
request.session['哈哈哈'] = '我来了'
request.session.set_expiry(1000) # 设置到期时间
# 判断用户之前访问的页面,登陆成功后定向到该页面
if user_visit_url:
return redirect(user_visit_url)
else:
return redirect(reverse('home')) # 反向解析重定向
return render(request, 'login_session.html')
@login_auth
def home(request):
return HttpResponse('home页面,登陆成功默认跳转的页面')
@login_auth
def page_a(request):
return HttpResponse('a页面,登陆成功才能访问的页面')
@login_auth
def page_b(request):
return HttpResponse('b页面,登陆成功才能访问的页面')
@login_auth
def logout(request):
# 登陆成功才能注销,所以也要加装饰器判断
# 清除客户端和服务端session信息
request.session.flush()
return redirect(reverse('login'))
这里大致和cookie部分相同
路由部分
# app02 urls
from django.urls import path
from app02 import views
# session模块使用
urlpatterns = [
path('login/', views.login, name='login'),
path('home/', views.home, name='home'),
path('a/', views.page_a),
path('b/', views.page_b),
path('logout/', views.logout),
]
通过name来实现反向解析
功能和cookie部分完全一样
cookie和session的基本使用就到此结束啦