一 .Django之CSRF
1.CSRF 簡介
跨站請求偽造(CSRF)與跨站請求腳本正好相反。跨站請求腳本的問題在於,客戶端信任服務器端發送的數據。跨站請求偽造的問題在於,服務器信任來自客戶端的數據。
無CSRF時存在的隱患
跨站請求偽造是指攻擊者通過HTTP請求江數據傳送到服務器,從而盜取回話的cookie。盜取回話cookie之后,攻擊者不僅可以獲取用戶的信息,
還可以修改該cookie關聯的賬戶信息。
2. CSRF在Django中
django為用戶實現防止跨站請求偽造的功能,通過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。
而對於django中設置防跨站請求偽造功能有分為全局和局部。 全局: 中間件 django.middleware.csrf.CsrfViewMiddleware 局部: @csrf_protect,為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置全局中間件。 @csrf_exempt,取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。 注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect
3. 處理csrf四種方法
django 第一次響應來自某個客戶端的請求時(get方式),會在服務器端隨機生成一個 token,然后把這個 token 寫在用戶請求的 cookie 里,同時也會給客戶端頁面發送一個隨機的 token (form表單中以{% csrf_token %}方式獲取)用以認證。之后客戶端每次以 POST 方式向服務端提交請求時,都會帶上這個 token,這樣就能避免被 CSRF 攻擊。 1.在返回的 HTTP 響應的 cookie 里,django 會為你添加一個 csrftoken 字段,其值為一個自動生成的 token;
2.在所有的 POST 表單中,必須包含一個 csrfmiddlewaretoken 字段 (只需要在模板里加一個 tag, django 就會自動幫你生成,見下面)
3.在處理 POST 請求之前,django 會驗證這個請求的 cookie 里的 csrftoken 字段的值和提交的表單里的 csrfmiddlewaretoken 字段的值是否一樣
。如果一樣,則表明這是一個合法的請求,否則,這個請求可能是來自於別人的 csrf 攻擊,返回 403 Forbidden.
4.在所有 ajax POST 請求里,添加一個 X-CSRFTOKEN header,其值為 cookie 里的 csrftoken 的值
4. 基本應用
直接在form表單中添加:就能應用。 {% csrf_token %} -----> 轉換成一個hidden屬性的input標簽 {{ csrf_token }} -----> 直接獲取csrf的隨機字符串 注意:本地的cookies中也會添加隨機字符串 ---> 注意key名
5 .全站禁用:
- 整個框架不使用csrf安全機制,直接在settings.py文件中注銷,整個網站都不再應用。 # 'django.middleware.csrf.CsrfViewMiddleware',
6 .局部禁用:全局使用,但是某些函數不需要應用
- settings.py文件中不注銷,在項目的views.py函數中導入模塊,給函數或是類加上對應方法的裝飾器: 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt #不再做檢測!其他沒加裝飾器的函數還是會檢測 def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok')
7. 局部使用:全局不使用,但是某些函數需要應用
# 'django.middleware.csrf.CsrfViewMiddleware', from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect #全站不用,某個函數需要使用認證的時候 def csrf1(request): if request.method == 'GET': return render(request,'csrf1.html') else: return HttpResponse('ok')
8 .特殊CBV:在CBV應用中
django 不認給類內的函數名上添加裝飾器,只能是在類上添加。
同時django限制若是應用裝飾器,必須用它的方法去添加,同時添加的語法格式也有限制。
from django.views import View from django.utils.decorators import method_decorator #必須使用這個方法 - 語法:@method_decorator(裝飾器函數名稱或方法,name='被裝飾的函數名') #先導入方法,然后裝飾器以參數的形式添加,其次指定要添加這個方法的函數名<樣式:name="函數名"> @method_decorator(csrf_protect,name='dispatch') class Foo(View): #請求來了,都是先執行類View的內置函數dispatch,然后再映射到對應的方法上! #所以給dispatch添加上就相當於給所有的方法添加了 def get(self,request): pass def post(self,request): pass
PS:CBV中添加裝飾器
#自定義的裝飾器 def wrapper(func): def inner(*args,**kwargs): return func(*args,**kwargs) return inner # 1. 指定方法上添加裝飾器 class Foo(View): @method_decorator(wrapper) #先導入方法,然后裝飾器以參數的形式添加 def get(self,request): pass def post(self,request): pass # 2. 在類上添加 @method_decorator(wrapper,name='dispatch') class Foo(View): def get(self,request): pass def post(self,request): pass
9. Ajax提交數據時候,攜帶CSRF
以post方式提交,放置在data中攜帶
<form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="user" type="text" name="user" /> <input type="submit" value="提交"/> <a onclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function submitForm(){ var csrf = $('input[name="csrfmiddlewaretoken"]').val(); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', data: { "user":user,'csrfmiddlewaretoken': csrf}, #注意csrf隨機字符串,后台有固定的名字接收,這種方式是通過標簽獲取的對應值 success:function(arg){ console.log(arg); } }) }
10 . AJAX 中POST方式提交,信息放在請求頭中,從cookies中獲取的csrf隨機字符串
<form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="user" type="text" name="user" /> <input type="submit" value="提交"/> <a onclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script src="/static/jquery.cookie.js"></script> <script> function submitForm(){ var token = $.cookie('csrftoken'); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', headers:{'X-CSRFToken': token}, #注意csrf隨機字符串后台有固定的名字接收 data: { "user":user}, success:function(arg){ console.log(arg); } }) } </script>
11. django csrf注意點
注意一定注意:ajax POST提交的時候,csrf-token 隨機字符串 直接放在data數據中的方式為:data:{csrfmiddlewaretoken:"{{ csrf_token }}"} 若是導入自己寫的JS文件,那上述方法就不能獲取到Django后台發送的隨機字符串,而是需要利用上面介紹的兩種方式獲取(頁面寫上{% csrf_token %},通過隱藏的input標簽取value值寫在POST
提交的data數據中;或是從cookie中獲取,寫在頭文件中。) 使用django框架時: 每次初始化一個項目時都要看看 django.middleware.csrf.CsrfViewMiddleware 這個中間件 每次在模板里寫 form 時都需要加一個 {% csrf_token %} tag 每次發 ajax POST 請求,都需要加一個 X_CSRFTOKEN 的 head