xss攻擊:假設咱們網站的評論裏面容許用戶寫js的時候,每一個人就會看到頁面會執行這個js代碼,有的是alert,不停的跳出彈框。這個還不算嚴重的,關鍵是若是js代碼運行的結果不顯示在頁面上,偷偷的 把cookie發到他本身那去,這樣攻擊者就可使用這個cookie登陸網站。ajax
CSRF:django
1.原理:cookie
發送請求,第一次打開頁面是get請求,請求數據,咱們不只把數據發送過去,並且還偷偷的發了一大堆字符串,這個字符串是加密的,只有本身能夠反解。xss
下一次咱們提交數據的時候,要帶着字符串來,這樣才容許提交,否則的話,就報錯,不容許提交數據。函數
這個通常體如今哪呢?post
咱們用django,若是咱們日後臺發送post的請求,咱們沒有把settings那個中間件註釋的話,頁面就直接出現403錯誤,好比:網站
我如今把那個代碼的註釋去掉:ui
咱們打開咱們的login頁面,無論寫什麼點擊提交,都會出現403錯誤:this
這個就是作了一層防禦,get提交方式沒有什麼問題,一旦你以post方式提交,後臺會先來去你發過來的請求裏面去找一下那個隨機字符串,這個是CSRF生成的字符串。加密
那咱們應該怎麼解決這個問題呢?人家這裏須要一個隨機字符串,咱們傳一個就能夠了。
在django的內部,也支持生成這個隨機的字符串:
在form中我加上這個一個變量:csrf_token:
咱們在刷新一下:
就多了一個字符串,這個字符串就是CSRF的token,之後再提交數據的時候就應該帶這個字符串。
可是咱們這樣在這裏放一個字符串是沒有用的,因此咱們要用到下面的東西:
咱們在頁面上沒有看到那個字符串了,可是咱們看一下生成的HTML代碼:
咱們生成了一個隱藏的input,咱們在提交數據的時候,後臺就可以拿到這個數據了,拿到了就能夠經過了。
那若是咱們沒有這個CSRFtoken,會出現什麼效果呢?
假設咱們先登陸咱們本身的網站,登陸成功以後 ,咱們先放着,咱們打開其餘的網站,提交表單登陸,提交到咱們的網站的網址上,若是咱們沒有這個token的話就直接提交了,可是若是有的話,其餘網站的表單不可能有咱們本身生成的token,就沒有辦法進行登陸,這樣就至關於作了一步防禦的工做。
上面是form表單提交數據,咱們使用的是csrf_token,那若是是ajax提交咱們應該怎麼作呢?
咱們上面看到了在HTML中生成了一個隱藏的input,裏面有一個字符串,其實在咱們的cookie中也生成了一個:
咱們若是ajax請求,咱們只須要拿到這個cookie的值,放到請求頭裏發過去就好了:
$(function(){ $('#btn').click(function(){ $.ajax({ url : '/login/', type : 'POST', data : {'user':'root','passwd':'123'}, headers : {'X-CSRFtoken' : $.cookie('csrftoken')}, success : function (data) { }, }); }); });
這樣就能夠提交成功!
固然若是咱們下面有不少ajax操做,咱們能夠在ajaxSetup中添加以後,下面的ajax就不須要了:
<!--在這個裏面能夠對全部的ajax作一個配置--> $.ajaxSetup({ beforeSend : function (xhr,settings) {<!--xhr:XMLHttpRequest 的對象,全部的ajax底層操做都是用這個,--> xhr.setRequestHeader('X-CSRFtoken' , $.cookie('csrftoken')); } })
在django中咱們還支持:
咱們在MIDDLEWARE中把CSRF註釋了,每一個form提交的時候都要加上一個token,不加就沒法進行驗證,做用於所有。這個很明顯是不合理的,由於有的時候咱們說那個函數就不須要加CSRFtoken,會有這種需求。
咱們如今有一個需求,100form提交中有2個須要用到CSRFtoken驗證,那怎麼作呢?
局部:
注:from django.views.decorators.csrf import csrf_exempt,csrf_protect
CSRF只有在post提交的時候才起做用,若是用get請求,那不須要csrftoken,那咱們能夠在上面的ajaxsetup中作判斷
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); } } });