django中间件及中间件实现的登录验证
1.定義
一個用來處理Django的請求和響應的框架級別的鉤子(函數),相對比較輕量級,并且在全局上改變django的輸入與輸出(使用需謹慎,否則影響性能)
直白的說中間件就是幫助我們在視圖函數執行之前和執行之后做一些額外操作
2.用處
用戶登錄
日志記錄
權限管理
請求驗證(post)
一般對所有請求做批量處理的時候用中間件,單獨對某幾個函數處理直接使用裝飾器
3.用法說明
我們使用django一直就在使用中間件,打開django的setting文件,當中的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', ]列表當中的每個字符串,其實是一個個類,即一個個中間件,它們正常的執行順序都是自上而下的
中間件中,我們可以定義五個方法,分別是:
process_request(self,request) process_view(self, request, view_func, view_args, view_kwargs) process_template_response(self,request,response) process_exception(self, request, exception) process_response(self, request, response)其中最常用的是process_request和process_response
以上方法的返回值可以是None或一個HttpResponse對象,如果是None,則繼續按照django定義的規則向后繼續執行,如果是HttpResponse對象,則直接將該對象返回給用戶。
3.1 圖例說明
這里還是先來看看django的生命周期圖例
?先從上圖了解django執行流程,每一步起了那些關鍵性作用,然后我們再來討論每一個中間件
3.2?process_request與process_response
process_request有一個request參數,這個和視圖函數中的request參數一模一樣
process_response有兩個參數,一個是request,一個是response,request和前面一致,response是視圖函數返回的HttpResponse對象
代碼實例
我在應用下創建了一個middlewares文件,用于存放中間件
from django.utils.deprecation import MiddlewareMixin # 注意導入路徑 class MD1(MiddlewareMixin):def process_request(self, request):print('我是MD1的process_request')def process_response(self, request, response):print('我是MD1的process_response')return responseclass MD2(MiddlewareMixin):def process_request(self, request):print('我是MD2的process_request')def process_response(self, request, response):print('我是MD2的process_response')return responsesetting.py文件配制添加的中間價位置
訪問一個視圖,終端輸出結果:
總結:
1.process_request方法,是在視圖函數執行之前執行的,當配制多個中間件時,會按照MIDDLEWARE中的注冊順序,也就是列表的索引值,從前到后依次執行的
返回值是None,繼續往后執行,返回值是HttpResponse的對象,執行對應中間件的process_response方法
2.對于視圖函數,是在process_request執行完畢后開始執行的
3.process_response方法,是在視圖函數之后執行的,而且多個中間件中的process_response方法是按照MIDDLEWARE中的注冊順序倒序執行的
3.3 process_view
process_view(self, request, view_func, view_args, view_kwargs)
該方法有四個參數:
request是HttpRequest對象。
view_func是Django即將使用的視圖函數。 (它是實際的函數對象,而不是函數的名稱作為字符串。)
view_args是將傳遞給視圖的位置參數的列表.
view_kwargs是將傳遞給視圖的關鍵字參數的字典。 view_args和view_kwargs都不包含第一個視圖參數(request)。
代碼實例
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, redirect, HttpResponseclass MD1(MiddlewareMixin):def process_request(self, request):print('我是MD1的process_request')def process_response(self, request, response):print('我是MD1的process_response')return responsedef process_view(self, request, view_func, view_args, view_kwargs):print('我是MD1的process_view')print(view_func, view_func.__name__)class MD2(MiddlewareMixin):def process_request(self, request):print('我是MD2的process_request')# return HttpResponse('MD2process_request')def process_response(self, request, response):print('我是MD2的process_response')return responsedef process_view(self, request, view_func, view_args, view_kwargs):print('我是MD2的process_view')print(view_func, view_func.__name__)
效果
總結:
1.process_view是在視圖執行前執行的,process_request之后,執行順序按照MIDDLEWARE中的注冊順序從前到后順序執行的
3.4 process_exception
process_exception(self, request, exception)
該方法兩個參數:
一個HttpRequest對象
一個exception是視圖函數異常產生的Exception對象。
?該方法只有在視圖函數中出現異常才會執行,如果視圖函數中無異常,process_exception方法不執行。
代碼實例
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, redirect, HttpResponseclass MD1(MiddlewareMixin):def process_request(self, request):print('我是MD1的process_request')def process_response(self, request, response):print('我是MD1的process_response')return responsedef process_view(self, request, view_func, view_args, view_kwargs):print('我是MD1的process_view')print(view_func, view_func.__name__)def process_exception(self, request, exception):print(exception, '這是MD1的process_exception')# return HttpResponse(str(exception))class MD2(MiddlewareMixin):def process_request(self, request):print('我是MD2的process_request')# return HttpResponse('MD2process_request')def process_response(self, request, response):print('我是MD2的process_response')return responsedef process_view(self, request, view_func, view_args, view_kwargs):print('我是MD2的process_view')print(view_func, view_func.__name__)# return HttpResponse('這是MD2的process_view')def process_exception(self, request, exception):print(exception, '這是MD2的process_exception')return HttpResponse(str(exception)) # 返回一個響應對象在視圖函數index中拋出一個異常
def index(request):print('app01中的index視圖')raise ValueError("6666")return HttpResponse('這是index頁面')此時結果:
# 可以從結果看出來,exception接收的就是異常信息,我們的MD1并沒有return HttpResponse(str(exception)) ,但是它卻也拋出了異常信息
總結:
1.只要視圖函數報錯了才執行
2.在視圖函數之后,process_response之前
3.5?process_template_response(不常用)
process_template_response是在視圖函數執行完成后立即執行,但是它有一個前提條件,那就是視圖函數返回的對象有一個render()方法
4.中間件執行流程
請求到達中間件之后,如果MIDDLEWARE中注冊了6個中間件,執行過程中,第3個中間件返回了一個HttpResponse對象,那么第4,5,6中間件的process_request和process_response方法都不執行,順序執行3,2,1中間件的process_response方法
process_request方法都執行完后,匹配路由找到要執行的視圖函數,先不執行視圖函數,先執行中間件中的process_view方法,process_view方法返回None,繼續按順序執行,所有process_view方法執行完后執行視圖函數。假如中間件3 的process_view方法返回了HttpResponse對象,則4,5,6的process_view以及視圖函數都不執行,直接從最后一個中間件,也就是中間件6的process_response方法開始倒序執行。
中間件的執行順序:
5.中間件實現登錄驗證
以下代碼還具有阻隔功能,即必須先登錄才能訪問主頁,直接從url訪問index會拒絕請求
代碼實例:
? urls.py
urlpatterns = [path('admin/', admin.site.urls),path('login/', views.login),path('logout/', views.logout),path('index/', views.index),path('home/', views.home), ] View Codeviews.py
from django.shortcuts import render, HttpResponse, redirect from django.contrib import auth import json# Create your views here. def login(request):if request.method == "POST":user = request.POST.get("user")pwd = request.POST.get("pwd")ret = {"status": 0, 'url': ''}if user == "xiao" and pwd == "123":# 設置sessionrequest.session["user"] = userret['status'] = 1# 跳轉到index頁面ret['url'] = '/index/'return HttpResponse(json.dumps(ret))return render(request, "login.html")def logout(request): # 注銷 auth.logout(request)return redirect("/login/")def index(request):return HttpResponse('this is index <a href="/logout/">注銷</a>')def home(request):return HttpResponse('this is home') View Code應用app01下的middlewares.py
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import render, redirect, HttpResponseclass AuthMD(MiddlewareMixin): # 驗證登錄white_list = ['/login/', ] # 白名單black_list = ['/black/', ] # 黑名單ret = {"status": 0, 'url': '', 'msg': ''} # 默認狀態def process_request(self, request): # 請求之前request_url = request.path_info # 獲取請求路徑# get_full_path()表示帶參數的路徑print(request.path_info, request.get_full_path())# 黑名單的網址限制訪問if request_url in self.black_list:self.ret['msg'] = "這是非法請求"self.ret['url'] = "/login/"# 白名單的網址或者登陸用戶不做限制# 判斷是否在白名單內或者已經有了session(表示已經登錄了)elif request_url in self.white_list or request.session.get("user"):return Noneelse:self.ret['msg'] = "請登錄后,再訪問!"self.ret['url'] = "/login/"# 錯誤頁面提示return render(request, "jump.html", self.ret) View Codesettings.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.middlewares.AuthMD', # 自定義中間件AuthMD ] View Codejump.html,用來做中間件不通過時,js跳轉
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> <link rel="stylesheet" href="http://mishengqiang.com/sweetalert/css/sweetalert.css"> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script src="http://mishengqiang.com/sweetalert/js/sweetalert-dev.js"></script> <div>{#獲取錯誤信息#}<input type="hidden" id="msg" value="{{ msg }}"><input type="hidden" id="url" value="{{ url }}"> </div><script>$(function () {var msg = $("#msg").val();var url = $("#url").val();console.log(msg);console.log(url);if (msg.length > 0) { //判斷是否有錯誤信息swal({title: msg,text: "2秒后自動關閉。",type: 'error',timer: 2000,showConfirmButton: false}, function () {window.location.href = url; //跳轉指定url});}}) </script></body> </html> View Code# 這里的定制化錯誤信息效果相當不錯,可以拿來借鑒
login.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>登錄</title><link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"><link rel="stylesheet" href="/static/css/signin.css"> </head> <body><div class="container"><form class="form-signin">{% csrf_token %}<h2 class="form-signin-heading">請登錄</h2><label for="inputUser" class="sr-only">用戶名</label><input type="text" id="inputUser" class="form-control" placeholder="用戶名" required="" autofocus="" name="user"><label for="inputPassword" class="sr-only">密碼</label><input type="password" id="inputPassword" class="form-control" placeholder="密碼" required="" name="pwd"><div class="checkbox"><label><input type="checkbox" value="remember-me"> 記住我</label></div><input class="btn btn-lg btn-primary btn-block" id="login" value="登陸"></form></div> <!-- /container --><script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> {#必須先引入jquery,再引入cookie#} <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.min.js"></script> {#sweetalert插件#} <link rel="stylesheet" href="http://mishengqiang.com/sweetalert/css/sweetalert.css"> <script src="http://mishengqiang.com/sweetalert/js/sweetalert-dev.js"></script> <script>//ajax在發送之前,做的header頭。csrfSafeMethod是一個方法名,用來調用的function csrfSafeMethod(method) {// these HTTP methods do not require CSRF protection//這些HTTP方法不需要CSRF保護// 匹配method的請求模式,js正則匹配用testreturn (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));}$('#login').click(function () {$.ajax({url: '/login/',type: 'post',//增加X-CSRFToken的請求頭headers:{ "X-CSRFToken":$.cookie('csrftoken') },data: {user: $('[name="user"]').val(),pwd: $('[name="pwd"]').val()},success: function (data) {data = JSON.parse(data);if (data.status) {swal({title: '登錄成功',type: 'success', //展示成功的圖片timer: 500, //延時500毫秒showConfirmButton: false //關閉確認框}, function () {window.location.href = data.url; //跳轉后臺首頁});}else {sweetAlert("登錄失敗!", data.msg, "error");}}})}) </script></body> </html> View Code?
更多專業前端知識,請上 【猿2048】www.mk2048.com
總結
以上是生活随笔為你收集整理的django中间件及中间件实现的登录验证的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: flask总结之session,webs
- 下一篇: react学习目录