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

Django框架(十八)—— 中介軟體、CSRF跨站請求偽造

中介軟體

一、什麼是中介軟體

中介軟體是介於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