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