十六 .Django CSRF的解決


 

一 .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

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM