昨日回顾
# 如果在浏览器上没有登陆,购买东西是能加入购物车,如果换了另一个浏览器,购物车就没有记录了,因为没有登录,所以存在了本地的浏览器的cookie中,登录后存在了服务端的数据库中
1 django中cookie的使用
-增 obj.set_cookie(key,value,max_age)
-删 obj.delete_cookie(key) # 或者将cookie的value设置为空
-查 request.COOKIE.get(key)
-改 obj.set_cookie(key,value,max_age)
2 django中session的使用(迁移数据库)
-增 request.session['key']=value
-删 del request.session['key']
-全部删除 request.session.flush():cookie和数据库都删除 request.session.delete()只删数据库
-查 request.session['key']
-改 request.session['key']=value
3 cbv加装饰器
-第一种:加在类上
from django.utils.decorators import method_decorator
@method_decorator(login_auth,name='get')
class UserList(views.View):
pass
-第二种:加在方法上
from django.utils.decorators import method_decorator
class UserList(views.View):
@method_decorator(login_auth)
def get(self):
pass
今日内容
1 django的session原理流程
2 自定义中间件
1 # 自定义步骤:原来的相同中间件要注释
-写一个类,一般写在app新py文件中继承MiddlewareMixin,导入from django.utils.deprecation import MiddlewareMixin
-里面写方法process_request(所有的请求来了,一定会触发它的执行,request就是当次请求的request对象)
-在setting中配置(注意,放在前和放在后是有区别的)
MIDDLEWARE = [
...
'app01.mymiddle.MyMiddleware1',
...
]
# 如果将自己写的类放在配置文件的最前面,而类中只写了process_request,那么不会经过中间件django.contrib.sessions.middleware.SessionMiddleware,因此在自己写的类中request.session中取不到
3process_request,process_response,process_view,process_exception
1 process_request(request对象) # 如果返回了,必须返回HttpResponse的对象,那么将相当于走process_request直接返回了,请求都没走到后面,如果没写,会继续走后面其他process_request。
2 process_response(request对象,response对象) # 所有的请求走了都会执行它,必须返回一个response ,否则在出了django框架之后,就没有任何返回东西
3 多个中间件,执行顺序是什么?
-请求来的时候从上往下执行:先执行每一个的process_request
-请求走的时候,从下往上执行:在执行每一个的process_response
# 前提是process_response的时候必须返回response,不然返回就直接断开了
4 # process_request可以干什么?
-写一个中间件,不管前端用什么编码,在requset.data中都有post的数据
-频率限制(限制某个ip地址,一分钟只能访问5次)
-登录认证(只要没登录,重定向到login路径)、
-记录用户访问日志(ip,时间,访问路径)
5 # process_response可以干什么?内部有response对象
-统一给所有(某几个路径)加cookie
-统一给所有(某几个路径)加响应头
-统一给所有的修改状态码或者响应体
6 process_view 路由匹配成功和视图函数执行之前执行(callback就是视图函数的内存地址)
def process_view(self, request, callback, callback_args, callback_kwargs):
# print(callback)
# print(callback_args) 参数
# print(callback_kwargs) 参数
res=callback(request) # 此就是视图函数,可以在这个之前或者之后写代码,就跟装饰器的作用一样,一般不这样用
return res
7 process_exception 视图函数出错,会执行它(全局异常捕获)(记录日志,哪个ip地址,访问哪个路径,出的错)
# 全局异常捕获,返回4开头的
def process_exception(self, request, exception):
print(exception)
return render(request,'error.html')
4 CSRF_TOKEN跨站请求伪造
1 跨站请求伪造
3 django解决了csrf攻击,中间件:django.middleware.csrf.CsrfViewMiddleware,该中间件只处理了post请求,在访问的时候,默认会在返回的页面中放入隐藏的随机字符串(js是无法操作另一个网页的)
4 后期中间件不能注释,每次发送post请求,都需要携带csrf_token随机字符串
# -form表单提交
-在form表单中 {% csrf_token%} 如果是{{ csrf_token }}就是一个变量
# 每次请求都会在context(渲染模板用的)里面放一个csrf_token,然后会在模板中写入返回,以后每次请求来的时候,根据request中的key,取出对应的字符串,校验是不是本服务端签发的。
# -ajax提交(如何携带)
方式一:放到data中
$.ajax({
url: '/csrf_test/',
method: 'post',
data: {'name': $('[name="name"]').val(), # 通过类,标签,或者属性取,此处是根据属性取
'password': $('[name="password"]').val(), 'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val() #此处的key的值必须是csrfmiddlewaretoken,此时取得值是直接从前端取出的
},
success: function (data) {
console.log('成功了')
console.log(data)
},
error: function (data) {
console.log('xxxxx')
console.log(data)
}
})
方式二:放到data中
'csrfmiddlewaretoken':'{{ csrf_token }}' # 注意'{{ csrf_token }}'此处一定要加''表示是字符串,此时取出的值是在后端渲染模板完成的值
方式三:从cookie中取出(此处取出的值和其他的值不一样)是放到请求头中,那么模板页面中就不需要写{% csrf_token%}
$.ajax({
url: '/csrf_test/',
method: 'post',
headers:{'X-CSRFToken':'{{csrf_token}}'},
})
# jquery.cookie.js 从请求头中取出cookie携带的csrf的随机字符串
-在浏览器中对cookie进行增,删,查,改
-前后端分离(js操作cookie)
# 全局使用,局部禁csrf
-在视图函数上加装饰器
from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 全局启用,局部禁用(中间件不能注释,这个视图函数,已经没有csrf校验了)
# @csrf_exempt
# def csrf_test(request):
# if request.method=='GET':
# return render(request,'csrf_test.html')
# else:
# name=request.POST.get('name')
# password=request.POST.get('password')
# print(name)
# print(password)
# return HttpResponse('登录成功')
# 全局禁用,局部使用csrf
@csrf_protect
def csrf_test(request):
if request.method=='GET':
return render(request,'csrf_test.html')
else:
name=request.POST.get('name')
password=request.POST.get('password')
print(name)
print(password)
return HttpResponse('登录成功')
# 古怪的使用方式,在urls.py中
path('csrf_test/', csrf_exempt(views.csrf_test)) #将视图函数当作参数传递给装饰器函数