Django框架之十 中介軟體 csrf跨站請求偽造
中介軟體
一、什麼是中介軟體
求的時候需要先經過中介軟體才能到達django後端(urls,views,templates,models)
響應的時候也需要經過中介軟體才能到達web服務閘道器介面
django預設的七個中介軟體
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中介軟體作用(********)
1.網站全域性的身份校驗,訪問頻率限制,許可權校驗。。。只要是涉及到全域性的校驗你都可以在中介軟體完成
2.django的中介軟體是所有web框架中做的最好的
三、中介軟體執行順序
-process_request()方法,從上往下執行 1.如果返回 HttpResponse物件,那麼會直接返回,不再往下執行而是跳到同級別的process_response方法,直接往回走 2.請求來的時候,會經過每個中介軟體裡面的process_request方法(從上往下) -process_response,從下往上執行 1.必須要將response形參返回,這個形參指代的就是要返回給前端的資料2.響應走的時候,會依次經過每一箇中間件裡面的process_response方法(從下往上)
四、自定義中介軟體
1.導包
from django.utils.deprecation import MiddlewareMixin
2.定義類,繼承MiddlewareMixin
在app01應用中建立一個資料夾mymiddleware,再建立一個mdd.py檔案
class MyMdd(MiddlewareMixin): def process_request(self,request): print('我是第一個中介軟體裡面的process_request方法') def process_response(self,request,response): print('我是第一個中介軟體裡面的process_response方法') return responseclassMyMdd1(MiddlewareMixin): def process_request(self,request): print('我是第二個中介軟體裡面的process_request方法') def process_response(self,request,response): print('我是第二個中介軟體裡面的process_response方法') return response
3.定義檢視函式
def index(request): print("view函式...") return HttpResponse("OK")
4.在settings中MIDDLEWARE註冊自定義中介軟體
MIDDLEWARE =[ 'mymiddleware.mdd.MyMdd', 'mymiddleware.mdd.MyMdd1', 'mymiddleware.mdd.MyMdd2', ]
5.設定路由
urlpatterns = [ url(r'^index/',view.index) ]
結果
我是第一個中介軟體裡面的process_request方法 我是第二個中介軟體裡面的process_request方法 view函式... 我是第二個中介軟體裡面的process_response方法 我是第一個中介軟體裡面的process_response方法
五、中介軟體五個可以自定義的方法
需要掌握的方法:
1.process_request()方法 請求來的時候會走該方法
1.請求來的時候 會經過每個中介軟體裡面的process_request方法(從上往下)
2.如果方法裡面直接返回了HttpResponse物件 那麼會直接返回 不再往下執行
基於該特點就可以做訪問頻率限制,身份校驗,許可權校驗
2.process_response()方法 響應回去的時候會走該方法
1.必須將response形參返回 因為這個形參指代的就是要返回給前端的資料
2.響應走的時候 會依次經過每一箇中間件裡面的process_response方法(從下往上)
需要了解的方法:
3.process_view()
在路由匹配成功執行檢視函式之前 觸發
4.process_exception()
當你的檢視函式報錯時,就會自動執行
5.process_template_response()
當你返回的HttpResponse物件中必須包含render屬性才會觸發 def index(request): print('我是index檢視函式') def render(): return HttpResponse('什麼鬼玩意') obj = HttpResponse('index') obj.render = render return obj
總結:
你在書寫中介軟體的時候,只要形參中有response,你就應該順手將其返回,這個response就是要給前端的資訊。 這五種方法有哪些特點: 1.都需要繼承MiddlewareMixin 2.在註冊中介軟體的時候,在settings中寫的路徑不能錯
CSRF——跨站請求偽造
1.什麼是CSRF攻擊
攻擊者盜用了你的身份,以你的名義傳送惡意請求,對伺服器來說這個請求是完全合法的。
比如釣魚網站
2.CSRF攻擊原理
要完成一次CSRF攻擊,受害者必須依次完成兩個步驟:
1.登入受信任網站A,並在本地生成Cookie。
2.在不登出A的情況下,訪問危險網站B。
釣魚網站例子
通過製作一個跟正兒八經的網站一模一樣的頁面,騙取使用者輸入資訊 轉賬交易從而做手腳 轉賬交易的請求確確實實是發給了中國銀行,賬戶的錢也是確確實實少了 唯一不一樣的地方在於收款人賬戶不對 內部原理 在讓使用者輸入對方賬戶的那個input上面做手腳 給這個input不設定name屬性,在內部隱藏一個實現寫好的name和value屬性的input框 這個value的值 就是釣魚網站受益人賬號
如何區分釣魚網站和正經網站?在正經網站返回頁面的時候,在form表單中偷偷塞一個特殊的字串,後端記下該頁面對應的字串的值,等使用者發post請求來的時候,我先去校驗特殊的字串是否匹配
如何去寫這個特殊的字串呢?模版語法有一個固定的寫法{% csrf_token %},必須寫在form表單內
3.CSRF攻擊防範
防止釣魚網站的思路 網站會給使用者訪問的form表單頁面 偷偷塞一個隨機字串 請求到來的時候 會先比對隨機字串是否一致 如果不一致 直接拒絕(403)
該隨機字串有以下特點
1.同一個瀏覽器每一次訪問都不一樣
2.不同瀏覽器絕對不會重複
4.CSRF在Django中的應用
1.在form表單中使用
<form action="" method="post"> {% csrf_token %} <p>username:<input type="text" name="username"></p> <p>password:<input type="text" name="password"></p> <input type="submit"> </form>
2.在ajax中使用,如何避免csrf校驗
- 有兩種方法,通過修改ajax的data
方法一:先在form表單頁面上寫{% csrf_token%},利用標籤查詢,獲取到該input鍵值訊息
data{'username':'jason','csrfmiddlewaretoken':$('[name=csrfmiddlewaretoken]').val()}
方法二:直接書寫'{{csrf_token}}'
data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
- 還可以將獲取隨機鍵值對的方法,寫到一個js檔案中,然後匯入這個檔案即可
新建一個js檔案,存放以下程式碼
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
5.CSRF禁用
1.CSRF全域性禁用
註釋掉settings中MIDDLEWARE的中介軟體 'django.middleware.csrf.CsrfViewMiddleware',
2.CSRF區域性禁用
- 在FBV中,直接載入FBV就行了(在頁面不加csrf_token情況下)
from django.views.decorators.csrf import csrf_exempt,csrf_protect
#(前提是全域性使用,沒有註釋csrf) 讓這個不用校驗,可以區域性使用
#當你網站全域性需要校驗csrf的時候,有幾個不需要校驗該如何處理 @csrf_exempt def login(request): return HttpResponse('login') #(前提是全域性禁用,註釋csrf,不會進行校驗) 設定就會進行校驗,區域性禁用
#當你網站全域性不校驗csrf的時候,有幾個需要校驗又該如何處理 @csrf_protect def lll(request): return HttpResponse('lll')
- 在CBV中,只能在dispatch方法或者類上面
from django.views import View from django.views.decorators.csrf import csrf_exempt,csrf_protect from django.utils.decorators import method_decorator # 這兩個裝飾器在給CBV裝飾的時候 有一定的區別 如果是csrf_protect 那麼有三種方式 # 第一種方式 # @method_decorator(csrf_protect,name='post') # 有效的 class MyView(View): # 第三種方式 # @method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res def get(self,request): return HttpResponse('get') # 第二種方式 # @method_decorator(csrf_protect) # 有效的 def post(self,request): return HttpResponse('post')
如果是csrf_exempt 只有兩種(只能給dispatch裝) 特例 @method_decorator(csrf_exempt,name='dispatch') # 第二種可以不校驗的方式 class MyView(View): # @method_decorator(csrf_exempt) # 第一種可以不校驗的方式 def dispatch(self, request, *args, **kwargs): res = super().dispatch(request, *args, **kwargs) return res def get(self,request): return HttpResponse('get') def post(self,request): return HttpResponse('post')