关于CSRF攻击原理在上一篇博客已经有过说明,这篇主要介绍下Django关于开启CSRF及CSRF工做机理。关于开启防护有两种,一种是全局开启,另外一种是局部开启。html
全局:前端
中间件 django.middleware.csrf.CsrfViewMiddlewarepython
局部:from django.views.decorators.csrf import csrf_exempt,csrf_protectjquery
@method_decorator(csrf_protect) class MyClassView(request): # 类视图逻辑 return render(request, "example.html")
{% csrf_token %}
,去生成随机的csrf token(key为csrfmiddlewaretoken的隐藏字段)当前端发送一个post请求时,后端会校验是否有一个csrf的随机字符串,若是没有就会报错。一般前端会发送post请求无外两种状况,一种是form表单的请求,另外一种是Ajax请求。ajax
对于form表单请求,咱们一般是在表单下添加{% csrf_token %}来自动生成字段名为csrfmiddlewaretoken,值为一段长长的字符串。经过审查前端代码,能够发现表单下隐藏着下面一段代码。
django
对于Ajax请求,上面的字段就不能经过{% csrf_token %}这种方法了。咱们须要从本地浏览器的cookie中获取。在cookie中这个字段名为
csrftoken,前端发过去的字段名为X-CSRFtoken,后台真正接收到的字段名变成了HTTP_X_CSRFTOKEN。后端
那为何从Django的控制台输出会获得HTTP_X_CSRFTOKEN呢?其实咱们前端的请求头X-CSRFtoken发送到后台以后,django会作一个名字处理,在原来的字段名前家一个HTTP_,而且将原来的小写字符变成大写的,“-”会处理成下划线“_”,因此会有这两个字段的不同。但本质上他们指向的都是同一个字符串。
jquery的ajax请求中为咱们封装了一个方法:ajaxSetup,它能够为咱们全部的ajax请求作一个集体配置,因此咱们能够进行以下改造,这样无论你的ajax请求有多少,均可以很方便地进行csrf验证了:浏览器
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/login/" method="POST"> {% csrf_token %} <input type="text" name="user" /> <input type="text" name="pwd" /> <input type="checkbox" name="rmb" value="1" /> 10s免登陆 <input type="submit" value="提交" /> <input id="btn" type="button" value="按钮"> </form> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> var csrftoken = $.cookie('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); } } }); $(function () { $('#btn').click(function () { $.ajax({ url:'/login/', type:"POST", data:{'username':'root','pwd':'123123'}, success:function (arg) { } }) }) }); </script> </body> </html>