cookie、session以及中间件
cookie
cookie是保存客户端浏览器上的键值对,是服务端设置在客户端浏览器上的键值对,也就意味着浏览器其实可以拒绝服务端的‘命令’,默认情况下浏览器都是直接让服务端设置键值对
设置cookie
obj1.set_cookie()
获取cookie
request.COOKIES.get()
删除cookie
obj1.delete_cookie()
cookie实现登陆功能
from functools import wraps
def login_auth(func):
@wraps(func)
def inner( request,*args,**kwargs):
if request.COOKIES.get('username'):
res=func( request,*args,**kwargs)
return res
else:
target_url=request.path_info ###获取到网页的url
return redirect('/login/?next=%s'%target_url)
return inner
def login(request):
if request.method=='POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'jason' and password == '123':
old_path = request.GET.get('next')
if old_path:
# 保存用户登录状态
obj = redirect(old_path)
else:
obj = redirect('/home/')
obj.set_cookie('name', 'lzs') # 让客户端浏览器 记录一个键值对
# obj.set_cookie('name','jason',max_age=5) # 让客户端浏览器 记录一个键值对
return obj
return render(request, 'login.html')
@login_auth
def home(request):
# if request.COOKIES.get('name'):
# return HttpResponse('我是主页,只有登陆了才能看')
# return redirect('/login/')
return HttpResponse('我是主页,只要登录了才能看')
@login_auth
def index(request):
return HttpResponse('我是index')
session
session是保存在服务器上的键值对,django session默认的过期时间是14天
设置session
request.session['key']=value 仅仅只会在内存产生一个缓存
1、django内部自动生成了随机的字符串
2、在django_session表中存入数据
3、将产生的随机的字符串发送给浏览器,让浏览器保存到cookie中
获取session
request.seesion.get('key')
1、浏览器发送cookie到django_session表中对比,是否有对应的数据
2、拿着随机字符串去django_session表中比对,取出赋值给request.session,
如果对不上那么request.session就是个空
(django session表是针对浏览器的,不同的浏览器来,才会有不同额记录)
删除session
request.session.delete() #只删除服务端的session
request.session.flush() #浏览器和服务端全部删除
session也可以设置超时时间
request.session.set_expiry(value 多种配置)
数字、0、不写、时间格式
from functools import wraps
def login_auth(func):
@wraps(func)
def inner(request,*args,**kwargs):
if request.session.get('username'):
res = func(request,*args, **kwargs)
return res
else:
target_url=request.path_info
return redirect('/login/?next=%s'%target_url)
return inner
def login(request):
if request.method=='POST':
username=request.POST.get('username')
password=request.POST.get('password')
old_path = request.GET.get('next')
print(old_path)
if username=='lzs' and password=='123':
request.session['username'] = username
if old_path:
obj= redirect(old_path)
else:
return redirect('/home/')
# obj.set_cookie('name', 'lzs')
return render(request,'login.html')
django中间件
- 用户访问频率限制
- 用户是否是黑名单
- 所有用户登录校验
- 只要涉及到网址全局的功能就该使用中间件
django中间件暴露给程序员五个可以自定义的方法(五个方法都是在特定的条件下自动触发的)
1、新建一个文件夹,里面新建一个任意名称的py文件,里面写类,固定继承类
from django.utils.deprecation import MiddlewreMixin
class MyMiddle(MiddlewareMixin):
2、去配置文件注册到中间件中,手写字符串的路径
'app01.mymiddleware.myaabb.MyMiddle1'
需要掌握:
process_request():
请求来的时候会从上往下经过每一个中间件里面,process_request一旦里面返回了
HttpResponse对象那么就不再往后执行了,会执行同一级别
eg:def process_request(self,request):
print('我是第一个自定义中间件里面的process_request方法')
return HttpResponse("我是第一个自定义中间件里面的HttpResponse对象返回值")
process_response():响应走的时候会从下往上依次经过每一个中间件里面process_response
eg:def process_response(self,request,response):
# response就是要返回给用户的数据
print("我是第一个自定义中间件里面的process_response方法")
return response
了解:
process_view:路由匹配成功之后执行视图函数之前触发
process_exception:当视图函数出现异常(bug)的时候自动触发
process_template_response:当视图函数执行完毕之后并且返回的对象中含有render方法的情况下才会触发
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class MyMiddle1(MiddlewareMixin):
def process_request(self,request):
print('我是第一个自定义中间件里面的process_request方法')
# return HttpResponse("我是第一个自定义中间件里面的HttpResponse对象返回值")
def process_response(self,request,response): # response就是要返回给用户的数据
print("我是第一个自定义中间件里面的process_response方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print(view_func,view_args,view_kwargs)
print('我是第一个自定义中间件里面的process_view方法')
def process_exception(self,request,exception):
print(exception)
print('我是第一个自定义中间件里面的process_exception方法')
def process_template_response(self,request,response):
print('我是第一个自定义中间件里面的process_template_response方法')
return response
class MyMiddle2(MiddlewareMixin):
def process_request(self,request):
print('我是第二个自定义中间件里面的process_request方法')
def process_response(self, request, response): # response就是要返回给用户的数据
print("我是第二个自定义中间件里面的process_response方法")
return response
def process_view(self,request,view_func,view_args,view_kwargs):
print(view_func,view_args,view_kwargs)
print('我是第二个自定义中间件里面的process_view方法')
def process_exception(self,request,exception):
print(exception)
print('我是第二个自定义中间件里面的process_exception方法')
def process_template_response(self,request,response):
print('我是第二个自定义中间件里面的process_template_response方法')
return response
跨站请求伪造(csrf)
就类似你搭建了一个跟银行一模一样的web页面,用户在你的网站转账的时候输入用户名、密码、对方账户,银行里面的钱确实少了,但是发现收款人变了
最简单的原理:
你写的form表单中用户的用户名、密码都会真实的提交给银行后台,但是收款账户却不是用户填的,你暴露给用户的是一个没有name属性的input框,你自己提前写好了一个带有name和value的input框
解决钓鱼网站的策略:
只要是用户想要提交post请求的页面,在返回给用户的时候提前设置好一个随机字符串,当用户提交post请求的时候,自动先查取是否有该随机字符串,如果有正常提交,没有直接报403
-
form表单:
你在写的时候只需加上一个{% csrf_token %}
-
ajax:
-
第一种自己在页面上先通过{% csrf_token %}获取随机字符串,然后利用标签查找
data:{'username':'jason','csrfmiddlewaretoken'😒('[name="csrfmiddlewaretoken"]').val()},
-
第二种:data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'},
-
第三种:拷贝js文件 </script src="/static/setup.js"></script/>
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
视图函数
csrf_exempt:只有两种装饰的方法
csrf_exempt 只有两种装饰的方式
csrf_exempt #某个视图函数不需要进行csrf校验
csrf_protect #某个视图函数需要进行csrf校验
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')
既然选择了远方,只能风雨兼程