Django 中 CSRF 理解
一、CSRF 使用:
Django 为用户实现防止跨站请求伪造的功能,通过中间件django.middleware.csrf.CsrfViewMiddleware
来完成。
全局设置中间件:
# 在setting.py 中 默认django 框架就会开启配置项
MIDDLEWARE = [
'django.middleware.csrf.CsrfViewMiddleware',
]
局部:
1.FBV模式局部使用:
-
@csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
# 'django.middleware.csrf.CsrfViewMiddleware', # 需要注释这一句话 from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect def csrf_test(request): if request.method == 'GET': return render(request,'csrf_test.html') else: return HttpResponse('ok')
-
@csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
'django.middleware.csrf.CsrfViewMiddleware', # 不注释 from django.views.decorators.csrf import csrf_exempt @csrf_exempt def csrf_test(request): if request.method == 'GET': return render(request,'csrf_test.html') else: return HttpResponse('ok')
-
导入:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
2.CBV模式局部使用:
-
局部禁用:在dispatch()方法上面添加 @csrf_exempt
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt, csrf_protect from django.shortcuts import render, HttpResponse from django.views import View class CsrfViews(View): @csrf_exempt def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): return HttpResponse('GET,响应内容') def post(self, request, *args, **kwargs): return HttpResponse('Post,响应内容')
-
局部使用:同样在dispatch()方法上添加django内置装饰器@method_decorator,将csrf_protect传入:
from django.views.decorators.csrf import csrf_exempt, csrf_protect from django.utils.decorators import method_decorator from django.shortcuts import render, HttpResponse from django.views import View class CsrfViews(View): @method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs) def get(self, request, *args, **kwargs): return HttpResponse('GET,响应内容') def post(self, request, *args, **kwargs): return HttpResponse('Post,响应内容')
-
method_decorator的使用:
name:这个参数是必备的,是为了装饰类中的get方法还是post方法
from django.utils.decorators import method_decorator # 将整个类都禁用,name='dispatch',无论什么方式请求,分发时都禁用 @method_decorator(csrf_exempt, name='dispatch') class CsrfViews(View): def get(self, request, *args, **kwargs): return HttpResponse('GET,响应内容') def post(self, request, *args, **kwargs): return HttpResponse('Post,响应内容')
二、原理:
当使用post提交数据时,Django会去检查是否有一个csrf的随机字符串
,如果没有就会报错,这也是上面我们提到要禁用或注释的原因:
三、通过FORM表单提交:
在form表单里面需要加{% csrf_token %}
总结:当用户访问/login页面的时候,会自动生成一个csrf随机字符串,并且cookie中也存放这个随机字符串,当用户再次提交数据的时候会带的这个随机字符串提交。
四、通过Ajax提交:
如果通过ajax进行提交数据,这里提交的csrftoken是通过请求头中存放
,需要提交一个字典类型
的数据,即这个时候需要一个key。
$("#btn1").click(function () {
$.ajax({
url:"/login/",
type:"POST",
data:{"usr":"root","pwd":"123456"},
# 因为cookie中同样存在csrftoken,所以value,可以直接从cookie中取
headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
success:function (arg) {
}
})
})
五、总结:
1.csrf在ajax提交的时候通过请求头传递给后台,通过key、value形式。
2.csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken。
3. csrf在form中提交的时需要在前端form中添加 {% csrftoken %} 。