關於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>