【Django】cookie和session
cookie和session
参考:https://www.cnblogs.com/yuanchenqi/articles/5716193.html
通俗理解cookie:
浏览器访问服务器的网站时,进入登录界面 登录成功,服务器发给浏览器一个cookie,浏览器将cookie保存在本地磁盘上。当浏览器再访问该网站的页面(如购物车)时发送的request请求会携带cookie 服务器识别到请求的cookie与自己数据库中cookie相同 则允许用户继续访问,否则会自动跳到登录页面。
详细解释cookie和session
1、cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生。 cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上cookie,这样服务器就能通过cookie的内容来判断这个是“谁”了。 2、cookie虽然在一定程度上解决了“保持状态”的需求,但是由于cookie本身最大支持4096字节(约4Kb),以及cookie本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是session。 问题来了,基于http协议的无状态特征,服务器根本就不知道访问者是“谁”。那么上述的cookie就起到桥接的作用。 我们可以给每个客户端的cookie分配一个唯一的id,这样用户在访问时,通过cookie,服务器就知道来的人是“谁”。然后我们再根据不同的cookie的id,在服务器上保存一段时间的私密资料,如“账号密码”等等。 3、总结而言:cookie弥补了http无状态的不足,让服务器知道来的人是“谁”;但是cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过cookie识别不同的用户,对应的在session里保存私密的信息以及超过4096字节的文本。 4、另外,上述所说的cookie和session其实是共通性的东西,不限于语言和框架 前几节的介绍中我们已经有能力制作一个登陆页面,在验证了用户名和密码的正确性后跳转到后台的页面。但是测试后也发现,如果绕过登陆页面。直接输入后台的url地址也可以直接访问的。这个显然是不合理的。其实我们缺失的就是cookie和session配合的验证。有了这个验证过程,我们就可以实现和其他网站一样必须登录才能进入后台页面了。 先说一下这种认证的机制。每当我们使用一款浏览器访问一个登陆页面的时候,一旦我们通过了认证。服务器端就会发送一组随机唯一的字符串(假设是123abc)到浏览器端,这个被存储在浏览端的东西就叫cookie。而服务器端也会自己存储一下用户当前的状态,比如login=true,username=hahaha之类的用户信息。但是这种存储是以字典形式存储的,字典的唯一key就是刚才发给用户的唯一的cookie值。那么如果在服务器端查看session信息的话,理论上就会看到如下样子的字典 {'123abc':{'login':true,'username:hahaha'}} 因为每个cookie都是唯一的,所以我们在电脑上换个浏览器再登陆同一个网站也需要再次验证。那么为什么说我们只是理论上看到这样子的字典呢?因为处于安全性的考虑,其实对于上面那个大字典不光key值123abc是被加密的,value值{'login':true,'username:hahaha'}在服务器端也是一样被加密的。所以我们服务器上就算打开session信息看到的也是类似与以下样子的东西 {'123abc':dasdasdasd1231231da1231231}
Django中的cookie
Django默认发送的cookie格式为:
{'csrftoken': 'zPglXV38MGIn3znrQ6JHNhz4UsWZ65SoGInzOnDVYrshlLjVpZz8cpsrlgwxij4p', 'sessionid': 'hb60ns6r1pe8bl805x7wxnsocekz3so5'}
借用一张别的大神画的图,可以更直观的看出来cookie和session的关系:
知道了原理,我们下面就来用代码实现
先在templates目录下创建两个html,login.html负责登录页面。index页面代表用户个人首页
views.py
from django.shortcuts import render,HttpResponse,redirect import datetime def login(request): print("COOKIES",request.COOKIES) print("session",request.session) if request.method =="POST": name = request.POST.get("user") pwd = request.POST.get("pwd") if name =="xiong" and pwd == "123456": # ret = redirect("/index/") # # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同 # ret.set_cookie("usernameis","xiongxiong",max_age=8) #组成键值对 # return ret # cookie +session 写法 request.session["is_login"] = True request.session["user"] = name return redirect("/index/") return render(request,"login.html") def index(request): ## request.COOKIES.get("usernameis", None) 取cookies中键名为usernameis 的值,取不到默认为空,如果不写None 取不到会报错 # if request.COOKIES.get("usernameis",None) == "xiongxiong": # name = request.COOKIES.get("usernameis",None) # return render(request,"index.html",locals()) if request.session.get("is_login",None): print(request.session) print(request.session["user"]) name = request.session.get("user",None) return render(request,"index.html",locals()) return redirect("/login/")
参考视图函数views.py 写法:
# /usr/bin/env python # coding:utf-8 from django.shortcuts import render from django.shortcuts import redirect def login(request): if request.method=="POST": username=request.POST['username'] pwd=request.POST['passwd'] if username=='abc' and pwd=='123': #设置session内部的字典内容 request.session['is_login']='true' request.session['username']='abc' #登录成功就将url重定向到后台的url return redirect('/backend/') #登录不成功或第一访问就停留在登录页面 return render(request,'login.html') def backend(request): """ 这里必须用读取字典的get()方法把is_login的value缺省设置为False, 当用户访问backend这个url先尝试获取这个浏览器对应的session中的 is_login的值。如果对方登录成功的话,在login里就已经把is_login 的值修改为了True,反之这个值就是False的 """ is_login=request.session.get('is_login',False) #如果为真,就说明用户是正常登陆的 if is_login: #获取字典的内容并传入页面文件 cookie_content=request.COOKIES session_content=request.session username=request.session['username'] return render(request,'backend.html', { 'cookie_content':cookie_content, 'session_content':session_content, 'username':username }) else: """ 如果访问的时候没有携带正确的session, 就直接被重定向url回login页面 """ return redirect('/login/') def logout(request): """ 直接通过request.session['is_login']回去返回的时候, 如果is_login对应的value值不存在会导致程序异常。所以 需要做异常处理 """ try: #删除is_login对应的value值 del request.session['is_login'] except KeyError: pass #点击注销之后,直接重定向回登录页面 return redirect('/login/')
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>个人首页</title> </head> <body> <form action="/login/" method="post"> <p>用户名:<input type="text" name="user" placeholder="用户名"></p> <p>密码:<input type="text" name="pwd" placeholder="密码"></p> <p><input type="submit" value="提交"></p> </form> </body> </html>
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录页面</title> </head> <body> <h2>登录成功-用户名为:{{ name }}</h2> </body> </html>
只有在输入了正确的用户名和密码之后才进入到了/backend/页面
从上图中我们看到有一下几点:
1、login页面正确登录的话,后台页面可以获取到浏览器携带的cookie的。
2、第一行的sessionid其实就是cookie值
3、session的内容是加密的,从客户端获取不到session的内容
4、服务端可以通过预设的key值取出session的内容并打印到前段
从火狐浏览器里查看cookie
django的session默认是存储在数据库里的,我们再到数据库查看一下真正session内容
---> session的工作流程:
最后我们再来最后的总结一下cookie和session的知识点:
一、操作Cookie
获取cookie:request.COOKIES[key]
设置cookie:response.set_cookie(key,value)
由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。
<script src='http://830909.blog.51cto.com/static/js/jquery.cookie.js'></script> $.cookie("list_pager_num", 30,{ path: '/' });
二、操作Session(session默认在服务器端保存15天)
获取session:request.session[key]
设置session:reqeust.session[key] = value
删除session:del request.session[key]
(这个删除其实就是把数据库的session_data更新为一个其他的值了,并没有立即删除)
request.session.set_expiry(value) * 如果value是个整数,session会在些秒数后失效。 * 如果value是个datatime或timedelta,session就会在这个时间后失效。 * 如果value是0,用户关闭浏览器session就会失效。 * 如果value是None,session会依赖全局session失效策略。
可以设置失效cookie天数
ret = redirect("/index/") # # max_age 和 expires都是设置cookie有效时间,一般情况下两者要设置相同 # ret.set_cookie("usernameis","xiongxiong",max_age=8) #usernameis和xiongxiong组成cookies键值对,max_age=8 8秒后cookie失效 ret.set_cookie("usernameis","xiongxiong",expires=datetime.datetime.utcnow()+datetime.timedelta(days=3)) #组成键值对