Django:Cookie和session
2.1Cookie
Cookie的由来
- HTTP协议是无状态的
- 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不会直接影响后面的请求响应情况。
- 状态可以理解为客户端和服务器在某次会话中产生的数据,那无状态的就以为这些数据不会被保留。会话中产生的数据又是我们需要保存的,也就是说要“保持状态”。因此Cookie就是在这样一个场景下诞生。
什么是Cookie
- Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
- cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,这样服务器就能通过Cookie的内容来判断这个是“谁”了。
查看Cookie
-
使用Chrome浏览器,打开开发者攻击查看
应用:
- 登录
- 保存浏览习惯
- 简单的投票
Django中操作Cookie
-
设置/获取Cookie
#第一种方法普通获取/设置: #set_cookie 设置 class Login(View): def get(self,request): pass def post(slef.request): #获取重定向对象 ret = redirect(url) ret.set_cookie("login","1")#设置cookie为{"login":"1"} ... #request.COOKIES.get(键) 获取 def login_required(func):#login_required函数是装饰器函数 def inner(request,*args,**kwargs): login = request.COOKIES.get("login") print(login) url = request.path_info if login != "1": return redirect("/login/?return_url={}".format(url)) ret = func(request,*args,**kwargs) return ret return inner @login_required def foo(request):... #第二种方法加密获取: #设置 rep.set_signed_cookie(key,value,salt='加密盐',...) 参数: key 键 value 值 max_age = None 超时时间 expires = None 超时时间(IE浏览器使用) path = "/" Cookie生效的路径 domain = None Cookie生效的域名 secure = False HTTPS传输 httponly = False 只能http协议传输,无法被JavaScript获取(但不是绝对,底层抓包可以获取到也可以被覆盖) #获取 request.get_signed_cookie('key', default="", salt='', max_age=None) 参数: key 键 value 值 max_age 后台控制过期时间 ret.set_signed_cookie("login", "1", salt="yan") login = request.get_signed_cookie("login",salt="yan",default="")
- 注意:当设置时候,不能有default="",当获取时候,应有default="",否则会报错
当set_signed_cookie 设置max_age=21秒,表示21秒后Cookie就失效
-
通过set_signed_cookie设置,get_signed_cookie获取 对比 set_cookie设置 ,request.COOKIES.get(键) 获取
两者都是成对出现,缺一都不能使用
set_signed_cookie设置会对cookies加密,但还是在Response Cookies显示出来,比如设置的1,在红色框内:
- 当设置secure = True,可以看到Response Cookies 中loginSecure中打✔,只有HTTPS才能继续登录。
-
httponly = True 只能HTTP协议登录
-
删除
- 用途:删除用户浏览器上之前设置的user的cookie值
ret = redirect("/login/") ret.delete_cookie("login")
-
示例:用户退出
def logout(request): ret= redirect("/login/")#退出回到登录页面 ret.delete_cookie("login")#清除Cookie return ret
2.2Session
session由来
-
需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性。这就是Session。
- 是由于Cookie本身最大支持4096字节。
- Cookie本身保存在客户端,可能被拦截或窃取。
-
Cookie弥补了HTTP无状态的不足,让服务器知道来的人是“谁”;但是Cookie以文本的形式保存在本地,自身安全性较差;所以我们就通过Cookie识别不同的用户,对应的在Session里保存私密的信息以及超过4096字节的文本。
-
session保存在服务器上一组组键值对(必须依赖cookie),不需要进行传输
-
session存的数据放在关联数据库的django-session表中
Session中方法
-
设置session
request.session[key] = values request.session.setdefault('k1',123)
-
获取session
request.session.get(key,None)
-
删除session
del request.session[key]
-
用session实现登录验证
class Login(View): def get(self,request): return render(request,"login.html") def post(self,request): username = request.POST.get("username") pwd = request.POST.get("pwd") obj = models.User.objects.filter(username=username,pwd=pwd) if obj: url = request.GET.get("return_url") if url: ret = redirect(url) else: ret = redirect("/home/") #设置session login request.session['login'] = 1 return ret return render(request,"login.html",{"error":"用户名密码不正确"}) def login_required(func):#装饰器,判断当前访问状态 def inner(request,*args,**kwargs): #获取session login = request.session.get("login") print(login) url = request.path_info if login != 1: return redirect("/login/?return_url={}".format(url)) ret = func(request,*args,**kwargs) return ret return inner @login_required def home(request): return render(request,"home.html") @login_required def index(request): return render(request,"index.html")
- 由图可以看出sessionid = 数据库存储的session_key
session流程分析:
- 流程图
- session表
- 浏览器
浏览器访问服务器,服务器会自动生成一个随机字符串,设置的值放置在一个字典当中,随机生成的字符串放在Django-session表中session-key字段,数据放在session-data中(加密后),expire_date是超时时间。并保存
把数据库session-key随机字符串放在cookie里返回给浏览器,也就是sessionid。可以理解为sessionid为cookie ,value为返回随机字符串
待到下次访问时会携带cookie(也就是sessionid),服务器会根据cookie从数据库中找到相应数据,再解密返回给浏览器。
由此可知session不能独立使用,必须依赖于cookie使用
session中其他方法
-
获取所有,键、值、键值对
request.session.keys() request.session.values() request.session.items()
-
获取session_key
request.session.session_key
-
失效日期数据删除
request.session.clear_expired()
-
示例:删除失效数据
-
-
检查会话session的key是否在数据库存在
request.session.exists("session_key")
-
request.session.exists("session_key")
def index(request): ret = request.session.session_key result= request.session.exists(ret) print(result)#True return render(request,"index.html")
-
-
删除当前会话所有session数据,不删除cookie
request.session.delete()
-
退出,并在库中信息删除
def logout(request): ret= redirect("/login/") request.session.delete() return ret
-
-
删除当前会话session数据并删除会话cookie
request.session.flush()
-
当执行此语句
-
-
设置会话session和Cookie的超时时间(超时后,cookie删除,但是数据库还有session)
request.session.set_expiry(value) 如果value是整整数,session会在相应秒数后失效 如果value是个datatime获取timedelta,session就会在这个时间后失效 如果value是0,用户关闭浏览器session就会失效 如果value是None,session会依赖全局session失效策略
-
示例:request.session.set_expiry(10)
-
Django中的Session配置
1. 数据库Session
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)
2. 缓存Session
SESSION_ENGINE = 'django.contrib.sessions.backends.cache' # 引擎
SESSION_CACHE_ALIAS = 'default' # 使用的缓存别名(默认内存缓存,也可以是memcache),此处别名依赖缓存的设置
3. 文件Session
SESSION_ENGINE = 'django.contrib.sessions.backends.file' # 引擎
SESSION_FILE_PATH = None # 缓存文件路径,如果为None,则使用tempfile模块获取一个临时地址tempfile.gettempdir()
4. 缓存+数据库
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db' # 引擎
5. 加密Cookie Session
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies' # 引擎
其他公用设置项:
SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)
SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)
SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)
SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)
SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)
小技巧:
-
如何看session配置
from django.conf import global_settings #ctrl + 鼠标左键点击global_settings进入文件global_settings.py然后搜索session,可以看到配置
-
缓存配置
from django.contrib.sessions.backends import db #ctrl + 鼠标左键点击db进入文件,通过以下操作可以看到session存在位置
3.JQuery的cookie操作
-
首先需要下载Jquery.cookie.js和jquery文件,jquery.cookie.js下载地址
http://plugins.jquery.com/cookie/
//连接jquery <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript" src="js/jquery.cookie.js"></script>
-
添加一个cookie
<script> var res = $.cookie("the_cookie","the_value"); console.log(res); </script>
-
创建一个cookie并设置有效时间为7天
$.cookie('the_cookie', 'the_value', { expires: 7, path: '/' });
-
读取cookie
$.cookie('the_cookie');
-
删除cookie
$.cookie('the_cookie', null); //通过传递null作为cookie的值即可
-
可选参数
$.cookie('the_cookie','the_value',{ expires:7, path:'/', domain:'jquery.com', secure:true })
-
参数
expires:(Number|Date)有效期;设置一个整数时,单位是天;也可以设置一个日期对象作为Cookie的过期日期; path:(String)创建该Cookie的页面路径; domain:(String)创建该Cookie的页面域名; secure:(Booblean)如果设为true,那么此Cookie的传输会要求一个安全协议,例如:HTTPS;
4.常用HTTP请求头
协议头 | 说明 | 示例 | 状态 |
---|---|---|---|
Accept | 可接受的相应内容类型(Content-Types ) |
Accept: text/plain | 固定 |
Accept-Charset | 可接受的字符集 | Accept-Charset: utf-8 |
固定 |
Accept-Encoding | 可接受的响应内容的编码方式。 | Accept-Encoding: gzip, deflate |
固定 |
Cache-Control | 用来指定当前的请求/回复中的,是否使用缓存机制。 | Cache-Control: no-cache |
固定 |
Cookie | 由之前服务器通过Set-Cookie (见下文)设置的一个HTTP协议Cookie |
Cookie: $Version=1; Skin=new; |
固定:标准 |
Host | 表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略。 | Host: www.itbilu.com:80``Host: www.itbilu.com |
固定 |
Referer | 表示浏览器所访问的前一个页面,可以认为是之前访问页面的链接将浏览器带到了当前页面。Referer 其实是Referrer 这个单词,但RFC制作标准时给拼错了,后来也就将错就错使用Referer 了。 |
Referer: http://itbilu.com/nodejs | 固定 |
User-Agent | 浏览器的身份标识字符串 | User-Agent: Mozilla/…… |
固定 |
Content-Type | 请求体的MIME类型 (用于POST和PUT请求中) | Content-Type: application/x-www-form-urlencoded | 固定 |
5.常见HTTP响应头
响应头 | 说明 | 示例 | 状态 |
---|---|---|---|
Cache-Control | 通知从服务器到客户端内的所有缓存机制,表示它们是否可以缓存这个对象及缓存有效时间。其单位为秒 | Cache-Control: max-age=3600 |
固定 |
Status | 通用网关接口的响应头字段,用来说明当前HTTP连接的响应状态。 | Status: 200 OK |
|
Location | 用于在进行重定向,或在创建了某个新资源时使用。 | Location: http://www.itbilu.com/nodejs | |
Server | 服务器的名称 | Server: nginx/1.6.3 |
固定 |
Date | 此条消息被发送时的日期和时间(以RFC 7231中定义的"HTTP日期"格式来表示) | Date: Tue, 15 Nov 1994 08:12:31 GMT | 固定 |
Connection | 客户端(浏览器)想要优先使用的连接类型 | Connection: keep-alive``Connection: Upgrade |
固定 |
Content-Length | 以8进制表示的请求体的长度 | Content-Length: 348 |
固定 |