Django Ajax CSRF認證(解決Post無法使用情況)

CSRF(Cross-site request forgery跨站請求僞造,也被稱爲“one click attack”或者session riding,通常縮寫爲CSRF或者XSRF。是一種對網站的惡意利用。

XSS

假如A網站有XSS漏洞,訪問A網站的攻擊用戶 用發帖的方式,在標題或內容等地方植入js代碼,這些代碼在某些場景下會被觸發執行(比如點回帖時)。

當A網站的其它用戶點回帖後,js運行了,這段js按道理可以做任何事,比如將用戶的cookie發到指定服務器(攻擊者所有),這樣攻擊者就可以使用cookie假冒用戶訪問A網站了,可以發貼,刪帖等。

 

CSRF

背景知識:瀏覽器在發送請求的時候,會自動帶上當前域名對應的cookie內容,發送給服務端,不管這個請求是來源A網站還是其它網站,只要請求的是A網站的鏈接,就會帶上A網站的cookie。瀏覽器的同源策略並不能阻止CSRF攻擊,因爲瀏覽器不會停止js發送請求到服務端,只是在必要的時候攔截了響應的內容。或者說瀏覽器收到響應之前它不知道該不該拒絕。

攻擊過程:用戶登陸A網站後,攻擊者自己開發一個B網站,這個網站會通過js請求A網站,比如用戶點擊了某個按鈕,就觸發了js的執行。

預防:

Double Submit Cookie

攻擊者是利用cookie隨着http請求發送的特性來攻擊。但攻擊都不知道 cookie裏面是什麼。

Django中是在表單中加一個隱藏的 csrfmiddlewaretoken,在提交表單的時候,會有 cookie 中的內容做比對,一致則認爲正常,不一致則認爲是攻擊。由於每個用戶的 token 不一樣,B網站上的js代碼無法猜出token內容,對比必然失敗,所以可以起到防範作用。

 

Synchronizer Token

和上面的類似,但不使用 cookie,服務端的數據庫中保存一個 session_csrftoken,表單提交後,將表單中的 token 和 session 中的對比,如果不一致則是攻擊。

這個方法實施起來並不困難,但它更安全一些,因爲網站即使有 xss 攻擊,也不會有泄露token的問題。

 

Django 中自帶了 防止CSRF攻擊的功能,但是一些新手不知道如何使用,給自己編程帶來了麻煩。常常會出現下面django csrf token missing or incorrect的錯誤。

GET 請求不需要 CSRF 認證,POST 請求需要正確認證才能得到正確的返回結果。一般在POST表單中加入 {% csrf_token %}

<form method="POST" action="/post-url/">
    {% csrf_token %}
     
    <input name='abc' value="Django">
</form>

如果使用Ajax調用的時候,就要麻煩一些。需要注意以下幾點:

  1. 在視圖中使用 render (而不要使用 render_to_response,danjgo3已經沒了)

  2. 1.使用 jQuery 的 ajax 或者 post 之前 加入這個 js 代碼(更改jquery源文件):

  3. /*====================django ajax ======*/
    jQuery(document).ajaxSend(function(event, xhr, settings) {
        function getCookie(name) {
            var cookieValue = null;
            if (document.cookie && document.cookie != '') {
                var cookies = document.cookie.split(';');
                for (var i = 0; i < cookies.length; i++) {
                    var cookie = jQuery.trim(cookies[i]);
                    // Does this cookie string begin with the name we want?
                    if (cookie.substring(0, name.length + 1) == (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
                }
            }
            return cookieValue;
        }
        function sameOrigin(url) {
            // url could be relative or scheme relative or absolute
            var host = document.location.host; // host + port
            var protocol = document.location.protocol;
            var sr_origin = '//' + host;
            var origin = protocol + sr_origin;
            // Allow absolute or scheme relative URLs to same origin
            return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
                (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
                // or any other URL that isn't scheme relative or absolute i.e relative.
                !(/^(\/\/|http:|https:).*/.test(url));
        }
        function safeMethod(method) {
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
    
        if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    });
    /*===============================django ajax end===*/

    2.或者在模板的html中加入這句話:

  4.     $.ajaxSetup({
          data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
        });

    即可使用post請求了。

  5.  

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章