Django 中間件

一.中間件

中間件就是介於request與response處理之間的一道處理過程,相對比較輕量級,而且在全局上改變django的輸入與輸出。由於改變的是全局,因此須要謹慎使用。python

Django中間件的定義:jquery

Middleware is a framework of hooks into Django’s request/response processing. 
It’s a light, low-level 「plugin」 system for globally altering Django’s input or output.

二.中間件用途

django的中間件,其實就是一個類,在請求到來和結束後,django會根據本身的規則在合適的時機執行中間件中相應的方法,因此若是須要修改請求,例如被傳送到view中的HttpRequest對象,或者是修改view返回的HttpResponse對象,就能夠經過中間件來實現。ajax

Django默認的中間件:django

在django項目的settings模塊中,有一個MIDDLEWARE變量瀏覽器

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',
]

請求傳遞到Django的過程以下:服務器

三.中間件方法

中間件的五個方法cookie

process_request(self,request)
process_view(self, request, callback, callback_args, callback_kwargs)
process_template_response(self,request,response)
process_exception(self, request, exception)
process_response(self, request, response)

中間件方法的運行流程圖:session

四.自定義中間件

第一步:導入MiddlewareMixinapp

from django.utils.deprecation import MiddlewareMixin

第二步:自定義中間件

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse

class MyMiddelware1(MiddlewareMixin):
    def process_request(self, request):
        print('MyMiddelware1=====>request')

    def process_response(self, request, response):
        print('MyMiddelware1======>response')
        # 返回response
        return response


class MyMiddelware2(MiddlewareMixin):
    def process_request(self, request):
        print('MyMiddelware2=====>request')

    def process_response(self, request, response):
        print('MyMiddelware2======>response')
        # 返回response
        return response

第三步:在view中定義一個視圖函數

def index(request):
    print('視圖函數')
    return HttpResponse('aaa')

第四步:在settings.py的MIDDLEWARE裏註冊本身定義的中間件

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',
    'app01.mymiddelware.MyMiddelware1',
    'app01.mymiddelware.MyMiddelware2',
]

結果:

MyMiddelware1=====>request
MyMiddelware2=====>request
視圖函數
MyMiddelware2======>response
MyMiddelware1======>response

注意:若是當請求到達process_request的直接不符合條件返回,程序將把請求直接發給其對應的process_response返回.而後依次返回到請求者,結果以下:

MyMiddelware1=====>request
MyMiddelware2=====>request
MyMiddelware2======>response
MyMiddelware1======>response

總結:

1.中間件的preocess_request方法是在執行視圖函數以前執行的
2.當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的
3.不一樣中間件之間傳遞的request都是同一個對象

process_view

process_view(self,request,callback, callback_args, callback_kwargs)

該方法由四個參數:

  • request是HttpResponse對象
  • callback是Django即將使用的視圖函數
  • callback_args是將傳遞給視圖的位置參數的列表
  • callback_kwargs是將傳遞給視圖的位置參數的字典

Django會在調用視圖函數以前調用process_view方法

它應該返回None或一個HttpResponse對象。 若是返回None,Django將繼續處理這個請求,執行任何其餘中間件的process_view方法,而後在執行相應的視圖。 若是它返回一個HttpResponse對象,Django不會調用適當的視圖函數。 它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果。

process_exception

process_exception(self,request,exception)

該方法有兩個參數:

  • request是HttpResponse對象
  • exception是視圖函數異常產生的Exception對象

這個方法只有在視圖函數中出現異常了才執行,它返回的值能夠是一個None也能夠是一個HttpResponse對象。若是是HttpResponse對象,Django將調用模板和中間件中的process_response方法,並返回給瀏覽器,不然將默認處理異常。若是返回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件註冊順序的倒序執行。

process_template_response

process_template_response(self,request,response)

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

五.CSRF_TIKEN跨站請求僞造

CSRF介紹:

CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲「One Click Attack」或者Session Riding,一般縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。儘管聽起來像跨站腳本(XSS),但它與XSS很是不一樣,XSS利用站點內的信任用戶,而CSRF則經過假裝來自受信任用戶的請求來利用受信任的網站。與XSS攻擊相比,CSRF攻擊每每不大流行(所以對其進行防範的資源也至關稀少)和難以防範,因此被認爲比XSS更具危險性

能夠這樣來理解:
       攻擊者盜用了你的身份,以你的名義發送惡意請求,對服務器來講這個請求是徹底合法的,可是卻完成了攻擊者所指望的一個操做,好比以你的名義發送郵件、發消息,盜取你的帳號,添加系統管理員,甚至於購買商品、虛擬貨幣轉帳等。 以下:其中Web A爲存在CSRF漏洞的網站,Web B爲攻擊者構建的惡意網站,User C爲Web A網站的合法用戶

CSRF攻擊防範:

1.驗證HTTP Referer字段
2.在請求地址中添加token並驗證(Django處理方式)
3.在HTTP頭中自定義屬性並驗證

在form表單中應用:

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

在AJAX中應用

<script>
    $(".btn").click(function () {
        $.ajax({
            url: '',
            type: 'post',
            data: {
                'name': $('[name="name"]').val(),
                'password': $("#pwd").val(),
                'csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()
                'csrfmiddlewaretoken':'{{ csrf_token }}'
            },
            success: function (data) {
                console.log(data)
            }

        })
    })
</script>

在HTTP頭中自定義屬性並驗證,放在cookie中:

獲取cookie:document.cookie

是一個字符串,能夠本身用js切割,也能夠用jquery插件

獲取cookie:$cookie('csrftoken')

設置cookie:$cookie('key','value')

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

六.局部禁用和使用csrf

全局禁用:註釋掉中間件 'django.middleware.csrf.CsrfViewMiddleware',

局部禁用:使用裝飾器,導入from django.views.decorators.csrf import csrf_exempt,csrf_protect

在FBV中使用:

from django.views.decorators.csrf import csrf_exempt,csrf_protect
# 再也不檢測,局部禁用(前提是全站使用)
# @csrf_exempt
# 檢測,局部使用(前提是全站禁用)
# @csrf_protect
def csrf_token(request):
    if request.method=='POST':
        print(request.POST)

        return HttpResponse('ok')
    return render(request,'csrf_token.html')

在CBV中使用:

# 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
相關文章
相關標籤/搜索