(day58)十、Cookie、Session、Token、Django中间件
一、Cookie
(一)由来
HTTP协议的无状态特性导致每次的请求都是独立的,即客户端和服务器在某次会话中产生的数据不会被保存,因此产生了Cookie,用来保存客户端的用户状态
(二)什么是Cookie
- Cookie具体是指服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些信息,以便服务器通过Cookie提取有用信息从而判断访问者
- Cookie最大支持4096字节,保存在客户端,安全性低
(三)Django中操作Cookie
(1)设置Cookie
普通
obj.set_cookie(key,value,...)
- obj为HttpResponse或render或redirect实例化的对象
- 加盐
obj.set_signed_cookie(key,value,salt='加密盐', max_age=None, ...)
- obj为HttpResponse或render或redirect实例化的对象
- 参数
- key:键
- value:值
- max_age:超时时间,以秒为单位,不能给IE设置cookie
- expires:超时时间,以秒为单位,可以给IE设置cookie
- path:cookie生效的路径,/表示根路径,可以被任何URL页面访问
- domain:cookie生效的域名
- secure:布尔值,是否为HTTPS传输
- httponly:布尔值,只能http协议传输,无法被JavaScript获取
# views.py
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'wick' and password == '123':
next_url = request.GET.get('next')
obj = redirect('/home/')
if next_url:
obj = redirect(next_url)
obj.set_cookie('whoami', 'wick',max_age=30)
return obj
return render(request, 'login.html')
(2)获取Cookie
获取cookie
request.COOKIES.get('key')
获取加盐的cookie值
request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
- default: 默认值
- salt: 加密盐
- max_age: 后台控制过期时间
from functools import wraps
def login_auth(func):
@wraps(func)
def inner(request,*args, **kwargs):
print(request.path_info)
print(request.get_full_path())
# 判断当前用户是否登录
if request.COOKIES.get('whoami'):
res = func(request,*args, **kwargs)
return res
else:
target_url = request.path_info
return redirect(f'/login/?next={target_url}')
return inner
(3)删除Cookie
obj.delete_cookie('key'):删除用户浏览器上之前设置的cookie值
@login_auth
def logout(request):
obj = redirect('/login/')
obj.delete_cookie('whoami')
return obj
二、Session
(一)由来
- 解决Cookie的安全性和存储限制问题
- 服务器生成并保存在服务器,可以存储超过4096字节的键值对(依赖于Cookie)
(二)Django中操作Session
- Django中Session存储在django_session表中,第一次使用时需执行迁移命令
- Django中Session失效时间默认是14天
- 同一个浏览器生成的session都会保存在django_session表中同一条数据中
(1)设置Session
设置Session时发生的事情:
- Django内部调用算法生成随机字符串
- 将随机字符串和加密后的数据(以及失效时间)存储到django_session表中
- 将随机字符串返回给浏览器,浏览器中以sessionid为键名保存为字典形式
设置Session值
request.session['k1'] = 123 request.session.setdefault('k1',123) # 存在则不设置
设置Session和Cooike的超时时间
request.session.set_expiry(value)
- 如果value是个整数,session会在些秒数后失效。
- 如果value是个datatime或timedelta,session就会在这个时间后失效。
- 如果value是0,用户关闭浏览器session就会失效。
- 如果value是None,session会依赖全局session失效策略
(2)获取Session
获取Session时发生的事情:
- Django内部会去请求头中获取cookie中的sessionid对应的随机字符串
- 将该字符串与django_session表中存储的随机字符串进行比对
- 比对成功,会把对应的加密后的数据获取出来,封装到request.session中,否则为空字典
获取Session
# 1. Session中数据 request.session['k1'] request.session.get('k1',None) # 2. 会话session的key request.session.session_key # 3. 检查会话session的key在数据库中是否存在 request.session.exists("session_key") # 4. 所有 键、值、键值对 request.session.keys() request.session.values() request.session.items() request.session.iterkeys() request.session.itervalues() request.session.iteritems()
(3)删除Session
- del request.session['k1']:删除Session中数据
- request.session.delete():删除当前会话的所有Session数据,数据库中也会删除
- request.session.flush() :删除当前的会话数据并删除会话的Cookie,数据库中也会删除
- request.session.clear_expired():将所有Session失效日期小于当前日期的数据删除,(Django中有自动动删除机制)
三、Django中间件
(一)什么是中间件
- 中间件是一个用来处理Django的请求和响应的框架级别的钩子,本质上是一个自定义类
- 可以全局范围内在视图函数执行前和施行后做一些额外的操作,比如用户登录校验、用户访问频率校验、用户权限校验
- Django中默认有七个中间件
# settings.py文件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
(二)自定义中间件
- 中间件可以定义五个方法
- 方法中参数request:必需参数,和视图函数中request一样
- 方法中返回值为None时, 继续按照django定义的规则向后继续执行
- 方法中返回值为HttpResponse对象时, 则直接将该对象返回给用户
# 在settings.py的MIDDLEWARE配置项中注册上述两个自定义中间件
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'app01.mymiddleware.mymidd.MyMidd1', # 自定义中间件MD1
'app01.mymiddleware.mymidd.MyMidd2' # 自定义中间件MD2
]
(1)process_request
- 默认按照自上而下的顺序执行MIDDLEWARE中每一个中间件内部的process_request方法
- 返回HttpResponse对象:请求会立刻停止从当前中间件的process_response 方法原路返回
# app01/mymiddleware/mymidd.py
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
(2) process_response
- 在视图函数之后 ,默认按照自下而上的顺序执行每个中间件中的process_response 方法
- 必须给方法传入两个形参,request和response
- 必须返回response:response是视图函数返回的HttpResponse对象 ,浏览器才能接受HttpResponse对象
# app01/mymiddleware/mymidd.py
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
(3) process_view
- 执行视图函数之前触发(路由匹配之后)
- 返回 HttpResponse对象 : 直接在中间件中掉头,倒叙执行一个个process_response方法,最后返回给浏览器
- 该方法有四个参数
- request: HttpRequest对象
- view_func:Django即将使用的视图函数对象
- view_args:将传递给视图的位置参数的列表.
- view_kwargs是将传递给视图的关键字参数的字典 (不包括request)
# app01/mymiddleware/mymidd.py
from django.utils.deprecation import MiddlewareMixin
class MD1(MiddlewareMixin):
def process_request(self, request):
print("MD1里面的 process_request")
def process_response(self, request, response):
print("MD1里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD1 中的process_view")
print(view_func, view_func.__name__)
class MD2(MiddlewareMixin):
def process_request(self, request):
print("MD2里面的 process_request")
pass
def process_response(self, request, response):
print("MD2里面的 process_response")
return response
def process_view(self, request, view_func, view_args, view_kwargs):
print("-" * 80)
print("MD2 中的process_view")
print(view_func, view_func.__name__)
(4) process_exception
- 视图函数出现错误异常自动触发,按照从下往上的顺序执行
- 两个参数 request 和 exception ( 视图函数异常产生的Exception对象 )
- 返回 HttpResponse对象 : 调用模板和中间件中的process_response方法,并返回给浏览器 (不会再执行process_exception 方法)
(5) process_template_response
- 视图函数执行完成后, 视图函数返回的对象有一个render()方法时才会执行,倒序执行
- 两个参数 request 和 response ,即必须返回response
(6)中间件执行流程
- 请求到达中间件, 先按照正序执行每个中间件的process_request方法 ,执行完后匹配路由
- 再顺序执行中间件中的process_view方法 ,执行完后执行视图函数
- 如果视图函数中有异常,会倒序执行process_exception
- 如果视图函数中返回对象有一个render()方法,会倒序执行process_exception方法
- 否则,会倒序执行process_response 方法,将响应发给客户端
- 方法中有response参数的必须返回response(process_template_response、process_response )
- 方法中没有response参数的(process_view、process_exception、process_response )
- 返回none:正常执行
- 返回HttpResponse的:会从当前中间件的response方法依次倒序执行,最终发送给客户端
以上,process_request、process_view默认为顺序,process_exception、process_exception、process_response 默认为倒序
四、Token(扩展)
(一)由来
客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比 ,对数据库和服务器压力大,因此产生了Token
(二)什么是Token
- Token是服务端生成的一串字符串
- 第一次登录时, 服务器生成一个Token返回给客户端
- 再次请求时, 客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码
(三)目的
减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮
(四)使用方式
(1) 设备号/设备mac地址作为Token
- 登录时将 设备号/mac地址 作为参数传给服务端
- 服务端接受后,用变量Token接收并保存在数据库,并将该Token设置到session中 ,下次请求只需比对变量Token
- 优点: 只要登录一次以后一直可以使用
缺点: 客户端需要带设备号/mac地址作为参数传递,而且服务器端还需要保存
若服务器的Token超时后,将客户端传递的Token向数据库中查询,同时并赋值给变量Token,如此,Token的超时又重新计时
(2) session值作为Token
- 携带用户名和密码登陆
- 服务端接受后判断,如果正确, 将本地获取sessionID 作为Token返回给客户端
- 好处:不用存储数据
- 缺点:session过期后要重新登录
(五)一些问题和解决方案
问题
在网络不好或者并发请求时会导致多次重复提交数据
解决方案( 将session和Token套用 )
- 可以对session进行加锁
- 把token放到session中,当后一个请求到来时,使用session中的token进行比对,当不一致时,即为重复提交,不允许通过
(day58)十、Cookie、Session、Token、Django中间件的更多相关文章
- Python 之 Django框架( Cookie和Session、Django中间件、AJAX、Django序列化)
12.4 Cookie和Session 12.41 cookie Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务 ...
- django基础之day10,cookie session token
https://www.cnblogs.com/Dominic-Ji/p/10886902.html cookie session token
- Cookie Session 和Django分页
cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...
- cookie, session, token 是什么 以及相应的安全考量
Cookie cookie 最常见的是用来保存一些账号信息,比如下图里的 记住账号 就是记录到了cookie里面 cookie 更主要的是针对和server通信的,我们知道http 是无状态的,那如果 ...
- Python Web学习笔记之Cookie,Session,Token区别
一.Cookie,Session,Token简介 # 这三者都解决了HTTP协议无状态的问题 session ID or session token is a piece of data that i ...
- cookie session token详解
cookie session token详解 转自:http://www.cnblogs.com/moyand/ 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, ...
- cookie,session,token介绍
本文目录 发展史 Cookie Session Token 回到目录 发展史 1.很久很久以前,Web 基本上就是文档的浏览而已, 既然是浏览,作为服务器, 不需要记录谁在某一段时间里都浏览了什么文档 ...
- cookie & session & token compare
cookie & session & token compare cookie.session.token 区别和优缺点 存储位置 cookie 存在 client 端 session ...
- cookie,session,token的定义及区别
参考了很多文章总结的. 1.cookie(储存在用户本地终端上的数据) 服务器生成,发送给浏览器,浏览器保存,下次请求同一网站再发送给服务器. 2.session(会话) a.代表服务器与浏览器的一次 ...
- cookie,session,token的理解
Get POST 区别异同点 淘宝token的 理解 过程算法 防止伪造请求 伪造相对难 简单发展史 登录的操作: 哪些人往自己的购物车中放商品, 也就是说我必须把每个人区分开,这就是一个 ...
随机推荐
- Ligg.EasyWinApp-100-Ligg.EasyWinForm:一款Winform应用编程框架和UI库介绍
本项目是一个Winform应用编程框架和UI库.通过这个该框架,不需任何代码,通过XML配置文件,搭建任意复杂的Windows应用界面,以类似Execel公式的方式实现基本的过程控制(赋值.条 ...
- 通过U盘在物理机安装CentOS出现Timeout的问题
错误信息:centos dracut timeout..... 解决方案: 在进入install页面是,按e,启动编辑.要保证Label与U盘的卷标保持一致即可.
- day97_11_29
一.数据存储到mongodb 爬取的数据如果需要存储到mongodb中,要通过item,定义一个存储类.再yield一个类. 数据存储的时候需要进过pipelines,再到setting中配置. fr ...
- Eclipse alt+/语法不提示的解决方法
最近公司电脑上的Eclipse没有了自动提示功能,也不是全部不提示,大多数情况下按下“alt+/”键还会产生提示,但是当我在java项目中邪main方法和syso的时候,“alt+/”则会失效,今天在 ...
- java之工厂方法设计模式
工厂方法模式是设计模式中应用最广泛的模式.在面向对象的编程中,对象的创建工作非常简单,对象的创建时机却很重要.工厂方法模式就是解决这个问题,它通过面向对象的手法,将所要创建的具体对象创建工作延迟到了子 ...
- C语言程序设计100例之(24):数制转换
例24 数制转换 题目描述 请你编一程序实现两种不同进制之间的数据转换. 输入格式 共三行,第一行是一个正整数,表示需要转换的数的进制n(2≤n≤16),第二行是一个n进制数,若n>10则用 ...
- kubernetes haproxy+keepalive实现master集群高可用
前言 master的HA,实际是apiserver的HA.Master的其他组件controller-manager.scheduler都是可以通过etcd做选举(--leader-elect),而A ...
- 如何关闭jdk自动更新提示
缘由 国庆将电脑重装了一下,jdk自然也就重装了,一开机总是提示我更新,索性就将他关掉. 解决办法 右键这个图标,点击属性. 将自动更新取消勾选.
- java spring是元编程框架---使用的机制是注解+配置
java spring是元编程框架---使用的机制是注解+配置
- (转)理解滑动平均(exponential moving average)
转自:理解滑动平均(exponential moving average) 1. 用滑动平均估计局部均值 滑动平均(exponential moving average),或者叫做指数加权平均(exp ...