cookie与session,还有中间件 cookie与session,还有中间件
一、cookie与session
1.1 cookie
HTTP协议是无状态的,如果需要保存数据,也就是“保持状态”,就需要用到cookie。
Cookie具体指的是一段小信息,它是服务器发送出来存储在浏览器上的一组组键值对,下次访问服务器时浏览器会自动携带这些键值对,以便服务器提取有用信息。
cookie的工作原理是:由服务器产生内容,浏览器收到请求后保存在本地;当浏览器再次访问时,浏览器会自动带上Cookie,服务器能通过Cookie的内容来判断用户身份。
obj = HttpRespones()
# 设置cookie
obj.set_cookie(key, value,...)
# 获取
request.CKKOIES.get()
# 删除
obj.delete_cookie()
# 设置标签
obj.set_signed_cookie(key, value, salt='加盐', max_age=None,...)
# 其他属性:dafault 默认值 expires 超过时间 domain 生效域名 path 路径
登录校验(cookie):
from django.shortcuts import render,HttpResponse,redirect
def login(request):
if request.mothed == 'POST':
username = request.POST.get('username')
pwd = request.POST.get('pwd')
if username == 'lalala' and pwd == '123':
old_path = request.GET.get('next')
if old_path:
# 保存用户一登陆状态
obj = redirect(old_path)
else:
obj = redirect('/home/')
obj.set_cookie('name', 'lalala') #让浏览器记录一个键值对
return obj
return render(request, 'login.html')
1.2 session
cookie一定程度上解决了保持状态的需求,但是由于其容量小(4096字节),而且保存在本地客户端,致使存在安全隐患。session保存在服务端,而且容量大,可以解决cookie安全性低的问题。
每个客户端的cookie被分配了唯一的id,服务端通过id识别用户身份,并将登录信息保存在session或者与已保存在session中的信息配对对比,完成身份存储和校验。
# 设置session
request.session['key'] = value # 此时进产生一个缓存
'''
1.django内部自动生成了随机的字符串
2.在django_session表中存入数据
session_key session_data date
随机字符串1 数据1 ...
随机字符串2 数据2 ...
随机字符串3 数据3 ...
3.将产生的随机字符串发送给浏览器 让浏览器保存到cookie中
sessionid:随机字符串
'''
# 获取session
request.session.get('key')
'''
1.浏览器发送cookie到django后端之后 django会自动获取到cookie值
2.拿着随机字符串去django_session表中比对 是否有对应的数据
3.如果比对上了 就讲随机字符串所对应的数据 取出赋值给request.session
4.如果对不上 那么request.session就是个空
注意:django session表是针对浏览器的,不同的浏览器来 才会有不同的记录
'''
# 删除session
request.session.delete() # 只删除服务端的session
request.session.flush() #浏览器和服务端的都删除
# 设置超时
request.session.set_expiry(value)
'''
value: 数字 --->数值秒后失效
0 --->关闭浏览器后失效
不写 --->依赖全局session失效
时间格式 --->时间后失效
django session默认的过期时间是14天
'''
# 检查key是否存在
request.session.exists('session_key')
# 删除所有失效日期小与当前日期的session
request.session.clear_expired
登录校验(session):
from functools impory wraps
def check_login(func):
@wraps(func)
def inner(request, *args, **wkargs):
next_url = request.get_full_path()
if request.session.get('user'):
return func(request, *args, **kwargs)
else:
return redirect('/login/?next={}'.format(next_url))
return inner
def login(request):
if request.method == 'POST':
user = request.POST.get('user')
pwd = request.POST.get('pwd')
if user == 'lalala' and pwd == '123':
# 设置session
request.session['user'] = user
# 获取到跳转到登录页面之前的url
next_url = request.GET.get('next')
if next_url:
return redirect(next_url)
else:
return redirect('/index/')
return render(request,'login.html')
@check_login
def logout(request):
request.session.delete()
return redirect('/login/')
@check_login
def index(request):
current_user = request.session.get('user',None)
return render(request,'index.html',{'user':current_user})
二、中间件
中间件是一个用来处理Django的请求和响应的框架级别的钩子。它是一个轻量、低级别的插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件都负责做一些特定的功能。
django中间件共有七层,每层功能各不一样,暴露给程序员五个可以自定义的方法(五个方法都是在特定的条件下自动触发的)。
# 1.新建一个任意名的py文件,写任意名的类,固定继承:
from django.utils.deprecation import MiddlewareMixin
class M(MiddlewareMixin):
...
# 2.在配置文件中注册中间件配置,手写路径
五种自定义方法:
# 1.process_request:优先于视图函数进行执行,如有多个中间件时,灰暗这MIDDLEWARE中注册顺序,从上向下依次执行。不同的中间件之间传递的request是同一个对象
# 2.process_response:落后于视图函数进行执行,按照倒叙的顺序进行。
# 3.process_view:路由匹配成功之后执行视图函数之前触发
# 4.process_exception:当视图函数出现异常(bug)的时候自动触发
# 5.process_template_response:当视图函数执行完毕之后并且返回的对象中含有render方法的情况下才会触发
三、跨站请求伪造
跨站请求伪造(Cross-site request forgery),也被称为 one-click attack 或session riding,通常缩写为 CSRF*或者 XSRF, 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
例如银行汇款,填写的form表单中,用户名密码都是真实提交给银行后台的,但是收款人的账户虽然填写的是被转账对象的,但是实际填写的是一个没有name属性的input框,实际转账的用户是提前写好的隐藏的带有name和value的input框。
解决方法:用户进入提交post请求的页面就返回一个随机的字符串,当用户提交请求时,会先自动校验这个字符串,正确就可以正常提交,匹配不正确就报403。
form表单:
<body>
<h1>真正的网站</h1>
<form action="" method="post">
{ % csrf_token % } # 加这条代码就可以
<p>username:<input type="text" name="username"></p>
<p>target_user:<input type="text" name="target_user"></p>
<p>money:<input type="text" name="money"></p>
<input type="submit">
</form>
</body>
ajax:
<body>
{ % csrf_token % }
<script>
%('#b1').click(function()){
$.ajax({
url:"",
type:"post",
data:{'username':'lalala'},
success:function(data){
alter(data)
}
})
}
</script>
</body>
# 方法一:data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
# 方法二:data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
方法一与方法二都是通过{% csrf_token %}获取到随机字符串,再利用标签查找。
方法三,导入一个相应功能的js文件。
四、CBV视图中使用装饰器
1.csrf_exempt:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
# 第一种
# @method_decorator(csrf_exempt,name='dispatch')
class MyCsrf(View):
# 第二种
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
除了csrf_exempt之外 所有的其他装饰器 在CBV上面都有三种方式:
@method_decorator(csrf_protect,name='post')
class MyCsrf(View):
@method_decorator(csrf_protect)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request,*args,**kwargs)
def get(self,request):
return HttpResponse('hahaha')
@method_decorator(csrf_protect)
def post(self,request):
return HttpResponse('post')