目錄html
中間件就是介於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(self,request,callback, callback_args, callback_kwargs)
該方法由四個參數:
Django會在調用視圖函數以前調用process_view方法
它應該返回None或一個HttpResponse對象。 若是返回None,Django將繼續處理這個請求,執行任何其餘中間件的process_view方法,而後在執行相應的視圖。 若是它返回一個HttpResponse對象,Django不會調用適當的視圖函數。 它將執行中間件的process_response方法並將應用到該HttpResponse並返回結果。
process_exception(self,request,exception)
該方法有兩個參數:
這個方法只有在視圖函數中出現異常了才執行,它返回的值能夠是一個None也能夠是一個HttpResponse對象。若是是HttpResponse對象,Django將調用模板和中間件中的process_response方法,並返回給瀏覽器,不然將默認處理異常。若是返回一個None,則交給下一個中間件的process_exception方法來處理異常。它的執行順序也是按照中間件註冊順序的倒序執行。
process_template_response(self,request,response)
該方法對視圖函數返回值有要求,必須是一個含有render方法類的對象,纔會執行此方法
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網站的合法用戶
1.驗證HTTP Referer字段 2.在請求地址中添加token並驗證(Django處理方式) 3.在HTTP頭中自定義屬性並驗證
<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>
<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>
獲取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>
全局禁用:註釋掉中間件 '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