赞
踩
早起的web应用都相对简单,只是简单的展示内容,无需记录用户的状态信息(例如登录状态等),后面随着web应用的发展web应用出现了获取用户状态信息等需求。
以用户登录状态为例,博客的收藏文档需要登录认证才会展现用户自己的收藏文档,那么就需要用户输入账号密码,但是频繁的输入账号密码会影响用户的体验,因此诞生了一次认证,多次使用的需求。
解决思路大体是服务端认证成功后,随机生成字符串,交给浏览器;之后浏览器访问都带上这个字符串交由服务端认证,认证通过则判定为已登录状态,无需多次输入账号密码。
cookie和session就是具体的解决方案
cookie
服务端保存在客户端浏览器上的信息,其表现形式一般是键值对(可以多个)
session
服务端保存在服务端的信息,其表现形式也是键值对。
session 在服务器端,cookie 在客户端。
session 用户无法查看和修改,cookie 用户可以查看修改。
session 和 cookie 的存储容量不同。
session 的实现依赖于 sessionID,而 sessionID 又存储在 cookie 上,所以,可以这么说:session 是基于 cookie 实现的一种数据存储方式。
cookie虽然是服务端告知浏览器的需要保存的信息,但浏览器也可以拒绝保存,不过这样会导致利用cookie的网页都将无法正常工作,例如无法记录用户的登录状态
cookie的设置
django的视图函数,其返回值都是基类HttpResponseBase的对象,该对象存在设置cookie的方法:set_cookie(),通过该方法我们可以为django 的每一次返回都附件cookie信息。
在设置cookie的时候可以添加一个超时时间
obj.set_cookie(‘username’, ‘jason666’,max_age=3,expires=3)
max_age
expires
两者都是设置超时时间的 并且都是以秒为单位
需要注意的是 针对IE浏览器必需使用expires
过期的cookie将会被浏览器清除
cookie的获取
浏览器保存cookie后,每次访问服务端都会带上cookie,django后端可以通过request.COOKIES.get(key)获取浏览器传来的cookie。依次进行认证。
cookie的删除
obj.delete_cookie(key),多用于类似退出登录这样的场景
需求:
设计一个web系统该系统有一个登录页面和若干个业务页面。
只有在登录认证过的状态下才能访问业务页面,否则都跳转到登陆页面。
跳转到登录并认证通过后,就能跳转到之前欲访问的目标页面。
登录页面文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head> <body> <h1>请登录</h1> <form action="" method="post"> 用户<input type="text" name="username"> 密码<input type="text" name="passwd"> <input type="submit"> </form> </body> </html>
视图层代码:
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def login_auth(func): def inner(request,*args,**kwargs): cookie=request.COOKIES.get('panks') if cookie: return func(request) else: print(request.get_full_path_info()) dest=request.get_full_path_info() return redirect('/login?next=%s'%dest) return inner def login(request): if request.method=='POST': username=request.POST.get('username') passwd = request.POST.get('passwd') if username=='panks' and passwd=='321': dest=request.GET.get('next') if dest: obj=redirect(dest) else: obj=redirect('/home') obj.set_cookie('panks','321') return obj return render(request, 'app01/login.html') @login_auth def index(request): return HttpResponse('这里是首页') @login_auth def home(request): return HttpResponse('这里是家目录')
上诉例子主要为了演示效果,实现对cookie认证来通过用户的登录认证,标记用户的状态为已登记,而对于cookie是认证没有太严谨。
实际项目中可以随机生成字符串代替上面的‘321’来设置cookie,并在cookie存储在redis等第三方数据库中,在执行login_auth时,可以从redis中取出原值对客户端提交的cookie进行校验。
session数据是保存在服务端的(在django框架中默认保存在数据库中)
返回给客户端的是一个随机字符串,客户端该随机字符串在服务端中以为session_key为键存储。
session的作用和cookie类似,用于分辨发起本次请求的用户状态。
在默认情况下django会自动创建django_session用于记录session数据,该表有三个字段:
session_key
服务端针对(没有带cookie或者cookie所对应的session已经过期又或者cookie查找不到对应session)的请求生成的一个随机字符串座位session_key,并以sessionid为键以该随机字符串为值组成一个cookie交给客户端;
session_data
暂时理解为后端设置的session键值对加密后的所得的字符串
expire_date
表示该session数据的过期时间,django默认session的过期时间是14天,但是你也可以人为的修改它
设置session
request.session[‘key’] = value
django内部流程:
获取session
request.session.get(‘key’)
django内部流程:
设置过期时间
request.session.set_expiry(),括号内可以放四种类型的参数:
1. 整数 多少秒
2. 日期对象 到指定日期就失效
3. 0 一旦当前浏览器窗口关闭立刻失效
4. 不写 失效时间就取决于django内部全局session默认的失效时间
清除session
request.session.delete() # 只删服务端的 客户端的不删
request.session.flush() # 浏览器和服务端都清空(推荐使用)
session是保存在服务端的 但是session的保存位置可以有多种选择
1.MySQL
2.文件
3.redis
4.memcache
…
一个计算机上(IP地址)的一个浏览器只会有一条session数据生效
当session过期的时候可能会出现多条数据对应一个浏览器,但是该现象不会持续很久,内部会自动识别过期的数据清除 你也可以通过代码清除,主要是为了节省服务端数据库资源
利用session机制重写cookie应用示例,需求不变,故前端代码无需变动,重写视图层
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def login_auth(func): def inner(request,*args,**kwargs): sessionId=request.session.get('panks') print(sessionId) if sessionId: return func(request) else: print(request.get_full_path_info()) dest=request.get_full_path_info() return redirect('/login?next=%s'%dest) return inner def login(request): if request.method=='POST': username=request.POST.get('username') passwd = request.POST.get('passwd') if username=='panks' and passwd=='321': dest=request.GET.get('next') if dest: obj=redirect(dest) else: obj=redirect('/home') request.session['panks']=321 return obj return render(request, 'app01/login.html') @login_auth def index(request): return HttpResponse('这里是首页') @login_auth def home(request): return HttpResponse('这里是家目录')
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。