HTTP被设计为”⽆态”,也就是俗称“脸盲”。 这⼀次请求和下⼀次请求 之间没有任
何状态保持,我们⽆法根据请求的任何⽅⾯(IP地址,⽤户代理等)来识别来⾃同⼀
⼈的连续请求。实现状态保持的⽅式:在客户端或服务器端存储与会话有关的数据
(客户端与服务器端的⼀次通信,就是⼀次会话),所以引入以下技术:

  • cookie
  • session

不同的请求者之间不会共享这些数据,cookie和session与请求者⼀⼀对应。

cookie是什么

cookies 是浏览器为 Web 服务器存的⼀小信息。 每次浏览器从某个服务器请求页面时,都会自动带上以前收到的cookie。cookie保存在客户端,安全性较差,注意不要保存敏感信息。典型应用:网站登录

设置Cookie

Django使用HttpResponse的set_cookie方法来设置对象,使用redirect重定向指定一个地址,用法:

1
2
3
response = redirect(reverse('admin:index'))
response.set_cookie(cookie名称, value='cookie值')
return response
参数 说明
key cookie的名称
value cookie的值,默认是空字符
max_age cookies的持续有效时间(以秒计),如果设置为 None,cookies 在 浏览器关闭的时候就失效了。
expires cookies的过期时间,格式:”Wdy, DD-Mth-YY HH:MM:SS GMT” 如果 设置这个参数,它将覆盖max_age。
path cookie⽣效的路径前缀,浏览器只会把cookie回传给带有该路径的⻚ ⾯,这样你可以避免将cookie传给站点中的其他的应⽤。/ 表示根路径,特殊的:根路径的cookie可以 被任何url的⻚⾯访问
domain cookie⽣效的站点。你可⽤这个参数来构造⼀个跨站cookie。如, domain=”.example.com” 所构造的,cookie对下⾯这些站点都是可 读的: www.example.com 、 www2.example.com。如果该参数设置为None,cookie只能由设置它的站点读取。
secure 如果设置为 True ,浏览器将通过HTTPS来回传cookie。
httponly 仅http传输 不能使⽤js获取cookie
  • set_signed_cookie

set_signed_cookie同set_cookie,不同点在于设置salt,即加盐,加密存储cookie数据:

1
response.set_signed_cookie('username', data['username'],salt='盐值')

获取cookie

获取cookies用于判断用户状态,确定前往页面。

1
2
3
4
5
6
username = request.COOKIES		# 获取用户请求的所有cookie
username = request.COOKIES.get('username') # 获取键名为username的cookie

#获取加“盐”的cookie
request.get_signed_cookie(key, default=RAISE_ERROR, salt='',
max_age=None)

删除cookie

删除cookie用于用户退出登录场景,服务器中把cookies删除,返回给浏览器,浏览器会清除本地cookie。

1
2
3
response = render(request, 'login.html')
response.delete_cookie('username')
return response

路由保护

路由保护简单理解为保护url地址不被非法请求,那些条件能访问,那些条件不能访问;比如后台管理,得全部保护,访问条件是管理员登录。

装饰器

Python修饰器就像注入一样,我把它理解成公用代码指定。先定义一个修饰器:

1
2
3
4
5
6
7
8
def check_login(func):
def inner(request, **kwargs): # 两个参数,第一个参数是request,第二个参数可以是多个参数
username = request.COOKIES.get('username') # 取到当前请求页面有没有cookie
if username: # 如果有cookie就调用被修饰的对象
return func(request, **kwargs)
else: # 负责重定向到登录页面
return redirect(reverse('admin:login'))
return inner

使用修饰器

在需要验证是否登录的视图函数前使用修饰器:

1
2
3
4
5
@check_login
def index(request):
# print(request.META['HTTP_USER_AGENT'])
active_ind = 'active'
return render(request, 'index.html', locals())

session

cookie看似解决了HTTP(短连接、⽆状态)的会话保持问题,但把全部⽤户数据 保存在客户端,存在安全隐患, 于是session出现了。我们可以 把关于⽤户的数据保存在服务端,在客户端cookie ⾥加⼀个sessionID(随机字符串)。其⼯作流程:

  • 当⽤户来访问服务端时,服务端会⽣成⼀个随机字符串;
  • 当⽤户登录成功后 把 {sessionID :随机字符串} 组织成键值对加到cookie⾥发 送给⽤户;
  • 服务器以发送给客户端 cookie中的随机字符串做键,⽤户信息做值,保存⽤ 户信息;
  • 再访问服务时客户端会带上sessionid,服务器根据sessionid来确认⽤户是否 访问过⽹站

seesion和cookie

  • 区别
    • session将数据存储与服务器端 cookie存储在客户端
    • cookie 存储在客户端,不安全,session存储在服务器端,客户端只存 sesseionid,安全
    • cookie在客户端存储值有⼤⼩的限制,⼤约⼏kb,session没有限制
  • 联系
    • session基于cookie实现

session配置

Django默认已经开启了session,配置位置:

1
2
3
4
5
6
INSTALLED_APPS = [
'django.contrib.sessions',
]
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
]

进⾏数据迁移,⽣成session使⽤的数据库表

1
2
python manage.py makemigrations	#生成数据库迁移文件
python manage.py migrate #执行迁移文件

session设置

session设置起来比cookies简单,cookies需要构造响应对象,seesion直接在request对象中设置即可自动返回sessionid到客户端:

1
request.session['username'] = username

seesion获取

获取也是调用request对象的seesion方法,返回键名值:

1
username = request.session.get('username')

session删除

  • clear() 清空所有session 但是不会将session表中的数据删除
  • flush() 清空所有 并删除表中的数据
  • logout() 退出登录 清除所有 并删除表中的数据
  • del req.session[‘key’] 删除某⼀个session的值
1
2
3
def logout(request):
request.session.flush()
return redirect(reverse('admin:login'))

session过期时间

1
req.session.set_expiry(5)	#单位是秒

系列文章

Django基础学习:https://www.xpctf.cn/posts/24c5/
Django晋级学习:https://www.xpctf.cn/posts/2f99/
Django模型学习:https://www.xpctf.cn/posts/d0b4/
Django会话学习:https://www.xpctf.cn/posts/7490/
Django Form学习:正在写