1. 程式人生 > >Django之CSRF

Django之CSRF

django django csrf

一、什麽是CSRF

CSRF, Cross Site Request Forgery, 跨站偽造請求。舉例來講,某個惡意的網站上有一個指向你的網站的鏈接,如果某個用戶已經登錄到你的網站上了,那麽當這個用戶點擊這個惡意網站上的那個鏈接時,就會向你的網站發來一個請求,你的網站會以為這個請求是用戶自己發來的,其實呢,這個請求是那個惡意網站偽造的。

Django為用戶實現跨站請求偽造保護的功能,通過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求偽造功能有分為全局設置和局部設置。


二、Django提供CSRF防護機制

Django第一次響應某個客戶端的請求時,會在服務器端隨機生成一個token,然後把這個token放到cookie中返回給客戶端。然後客戶端每次POST請求時都會帶上這個token,這樣就避免了CSRF攻擊。

  • 在返回的HTTP響應的cookie中,Django會添加一個csrftoken字段,值為隨機生成的token

  • 在POST表單中,必須包含一個csrfmiddlewaretoken隱藏字段,需要在模板中添加{% csrf_token %}自動生成

  • 在處理POST請求之前,Django會驗證cookie中csrftoken和表單中csrfmiddlewaretoken的值是否一致。如果一致,則表明這是一個合法請求。否則這個請求就是偽造的,返回403 Forbidden。

  • 在Ajax POST請求中,添加一個"X-CSRFToken"頭部,值為cookie中的csrftoken的值。


三、CSRF設置

1. 全局設置(中間件)

django.middleware.csrf.CsrfViewMiddleware

2. 局部設置(視圖函數)

from django.views.decorators.csrf import csrf_exempt,csrf_protect

@csrf_protect  # 為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置CSRF中間件。
def func():
    pass
    
@csrf_exempt  # 取消當前函數防跨站請求偽造功能,即便settings中設置了CSRF中間件。
def func():
    pass


四、應用CSRF

1. 前端Form表單中設置CSRF

<form method="post">
{% csrf_token %}
    ...
</form>

2. 自動在每個Ajax請求頭部中添加"X-CSRFToken"

// 導入jquery.cookie.js 通過$.cookie('csrftoken')獲取csrf_token
// beforeSend在每個Ajax請求之前自動設置請求頭部"X-CSRFToken"

<script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
	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);
			}
		}
	});
</script>

3. 單獨在Ajax請求中設置"X-CSRFToken"頭部

<script src="/static/plugin/jquery/jquery-1.8.0.js"></script>
<script src="/static/plugin/jquery/jquery.cookie.js"></script>
<script type="text/javascript">
	$.ajax({
	    headers:{"X-CSRFToken":$.cookie('csrftoken')},
	    ...
        })
</script>


Django之CSRF