1. 程式人生 > >Django框架(十八)—— 中間件、CSRF跨站請求偽造

Django框架(十八)—— 中間件、CSRF跨站請求偽造

exce meta messages options prot function port 信任 隨機

中間件

一、什麽是中間件

中間件是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全局上改變django的輸入與輸出

技術分享圖片

二、中間件的作用

如果你想修改請求,例如被傳送到view中的HttpRequest對象。 或者你想修改view返回的HttpResponse對象,這些都可以通過中間件來實現。

可能你還想在view執行之前做一些操作,這種情況就可以用 middleware來實現。

Django默認的中間件:(在django項目的settings模塊中,有一個 MIDDLEWARE_CLASSES 變量,其中每一個元素就是一個中間件。每一個中間件都有具體的功能

MIDDLEWARE = [
    ‘django.middleware.security.SecurityMiddleware‘,
    ‘django.contrib.sessions.middleware.SessionMiddleware‘,
    ‘django.middleware.common.CommonMiddleware‘,
    ‘django.middleware.csrf.CsrfViewMiddleware‘,
    ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,
    ‘django.contrib.messages.middleware.MessageMiddleware‘,
    ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,
]

三、中間件執行順序

-process_request,從上往下執行
        如果retrun HttpResponse的對象,直接返回了
        如果retrun None ,繼續往下走
-process_response,從下往上執行
        必須要retrun Httpresponse的對象

技術分享圖片

四、自定義中間件

1、導包

from django.utils.deprecation import MiddlewareMixin

2、定義類,繼承MiddlewareMixin

在app01中創建一個py文件——mymiddelware

class Md1(MiddlewareMixin):

    def process_request(self,request):
        print("Md1請求")
        # 返回None的時候,繼續往下走
        # 返回HttpRspons對象,直接返回,走自己的process_response
 
    def process_response(self,request,response):
        print("Md1返回")
        return response
    
class Md2(MiddlewareMixin):

    def process_request(self,request):
        print("Md2請求")
 
    def process_response(self,request,response):
        print("Md2返回")
        return response

3、在視圖函數中定義一個函數

def index(request):
    print("view函數...")
    return HttpResponse("OK")

4、在settings的MIDDLEWARE中註冊自定義的中間件

MIDDLEWARE = [
                ‘app01.mymiddelware.MyMiddleware1‘,
                ‘app01.mymiddelware.MyMiddleware2‘,
                ]

結果為

Md1請求
Md2請求
view函數...
Md2返回
Md1返回

五、中間件的方法

1、process_request

請求來的時候,會走該方法

def process_request(self,request):

2、process_response

響應回去的時候,會走該方法

 def process_response(self,request,response):

3、process_view

它應該返回None或一個HttpResponse對象。

如果返回None,Django將繼續處理這個請求,執行任何其他中間件的process_view方法,然後在執行相應的視圖。

如果它返回一個HttpResponse對象,Django不會調用適當的視圖函數。 它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果

def process_view(self, request, view_func, view_args, view_kwargs):
# request是HttpRequest對象。
# view_func是Django即將使用的視圖函數。 (它是實際的函數對象,而不是函數的名稱作為字符串。)
# view_args是將傳遞給視圖的位置參數的列表.
# view_kwargs是將傳遞給視圖的關鍵字參數的字典。 view_args和view_kwargs都不包含第一個視圖參數(request)。

4、process_exception

這個方法只有在視圖函數中出現異常了才執行

5、process_template_response

該方法對視圖函數返回值有要求,必須是一個含有render方法類的對象,才會執行此方法

六、CSRF——跨站請求偽造

1、什麽是CSRF攻擊

攻擊者盜用了你的身份,以你的名義發送惡意請求,對服務器來說這個請求是完全合法的

2、CSRF攻擊原理

技術分享圖片

要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:

  1.登錄受信任網站A,並在本地生成Cookie。

  2.在不登出A的情況下,訪問危險網站B。

3、CSRF攻擊防範

1、通過refer
2、加一個隨機字符串校驗(加載請求的路徑裏,加載請求體中)
3、在請求頭中加字符串校驗

4、CSRF在Django中的應用

(1)在form表單中應用

<form action="" method="post">
    {% csrf_token %}
    <p>用戶名:<input type="text" name="name"></p>
    <p>密碼:<input type="text" name="password"></p>
    <p><input type="submit"></p>
</form>

(2)在Ajax中應用

  • 放在data中
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    
    {% csrf_token %}
    
    <p>用戶名:<input type="text" name="name"></p>
    <p>密碼:<input type="text" name="password" id="pwd"></p>
    <p><input type="submit"></p>
</form>
<button class="btn">點我</button>
</body>
<script>
    $(".btn").click(function () {
        $.ajax({
            url: ‘‘,
            type: ‘post‘,
            data: {
                ‘name‘: $(‘[name="name"]‘).val(),
                ‘password‘: $("#pwd").val(),
                // 
                ‘csrfmiddlewaretoken‘: $(‘[name="csrfmiddlewaretoken"]‘).val()
            },
            success: function (data) {
                console.log(data)
            }

        })
    })
</script>
</html>
  • 放在cookie中

獲取cookie:document.cookie

是一個字符串,可以自己用js切割,也可以用jquery的插件

獲取cookie:$.cookie(‘csrftoken‘)

設置cookie:$.cookie(‘key‘,‘value‘)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="/static/jquery-3.3.1.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    {% csrf_token %}
    <p>用戶名:<input type="text" name="name"></p>
    <p>密碼:<input type="text" name="password" id="pwd"></p>
    <p><input type="submit"></p>
</form>
<button class="btn">點我</button>
</body>
<script>
    $(".btn").click(function () {
        var token=$.cookie(‘csrftoken‘)
        //var token=‘{{ csrf_token }}‘
        $.ajax({
            url: ‘‘,
            headers:{‘X-CSRFToken‘:token},
            type: ‘post‘,
            data: {
                ‘name‘: $(‘[name="name"]‘).val(),
                ‘password‘: $("#pwd").val(),
            },
            success: function (data) {
                console.log(data)
            }

        })
    })
</script>
</html>

5、CSRF禁用

(1)全局禁用

全站禁用:註釋掉settings中MIDDLEWARE的中間件 ‘django.middleware.csrf.CsrfViewMiddleware‘,

(2)局部禁用

  • 在FBV中,直接加載fbv上就行了
from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 不再檢測,局部禁用(前提是全局使用)
# @csrf_exempt
@csrf_exempt
def csrf_disable(request):
    print(request.POST)
    return HttpResponse(‘ok‘)

# 檢測,局部使用(前提是全局禁用)
# @csrf_protect
 def csrf_disable(request):
    print(request.POST)
    return HttpResponse(‘ok‘)
  • 在CBV中,只能加在dispatch方法或者類上面
# CBV中使用
from django.views import View
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
# CBV的csrf裝飾器,只能加載類上(指定方法為dispatch)和dispatch方法上(django的bug)
# 給get方法使用csrf_token檢測
@method_decorator(csrf_exempt,name=‘dispatch‘)
class Foo(View):
    def get(self,request):
        pass
    def post(self,request):
        pass
    # @method_decorator(csrf_protect)
    def dispatch(self, request, *args, **kwargs):
        ret=super().dispatch(request, *args, **kwargs)
        return ret

Django框架(十八)—— 中間件、CSRF跨站請求偽造