實現(xiàn)登錄驗證
創(chuàng)新互聯(lián)服務項目包括平橋網站建設、平橋網站制作、平橋網頁制作以及平橋網絡營銷策劃等。多年來,我們專注于互聯(lián)網行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網行業(yè)的解決方案,平橋網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到平橋省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
我們繼續(xù)來完善投票應用。在上一個章節(jié)中,我們在用戶登錄成功后通過session保留了用戶信息,接下來我們可以應用做一些調整,要求在為老師投票時必須要先登錄,登錄過的用戶可以投票,否則就將用戶引導到登錄頁面,為此我們可以這樣修改視圖函數(shù)。
def praise_or_criticize(request: HttpRequest): """投票""" if 'username' in request.session: try: tno = int(request.GET.get('tno', '0')) teacher = Teacher.objects.get(no=tno) if request.path.startswith('/praise'): teacher.good_count += 1 else: teacher.bad_count += 1 teacher.save() data = {'code': 200, 'message': '操作成功'} except (ValueError, Teacher.DoesNotExist): data = {'code': 404, 'message': '操作失敗'} else: data = {'code': 401, 'message': '請先登錄'} return JsonResponse(data)
前端頁面在收到{'code': 401, 'message': '請先登錄'}后,可以將用戶引導到登錄頁面,修改后的teacher.html頁面的JavaScript代碼部門如下所示。
注意:為了在登錄成功之后能夠回到剛才投票的頁面,我們在跳轉登錄時設置了一個backurl參數(shù),把當前瀏覽器中的URL作為返回的頁面地址。
這樣我們已經實現(xiàn)了用戶必須登錄才能投票的限制,但是一個新的問題來了。如果我們的應用中有很多功能都需要用戶先登錄才能執(zhí)行,例如將前面導出Excel報表和查看統(tǒng)計圖表的功能都加以登錄限制,那么我們是不是需要在每個視圖函數(shù)中添加代碼來檢查session中是否包含了登錄用戶的信息呢?答案是否定的,如果這樣做了,我們的視圖函數(shù)中必然會充斥著大量的重復代碼。編程大師 Martin Fowler曾經說過:代碼有很多種壞味道,重復是最壞的一種。在Django項目中,我們可以把驗證用戶是否登錄這樣的重復性代碼放到中間件中。
Django中間件概述
中間件是安插在Web應用請求和響應過程之間的組件,它在整個Web應用中扮演了攔截過濾器的角色,通過中間件可以攔截請求和響應,并對請求和響應進行過濾(簡單的說就是執(zhí)行額外的處理)。通常,一個中間件組件只專注于完成一件特定的事,例如:Django框架通過SessionMiddleware中間件實現(xiàn)了對session的支持,又通過AuthenticationMiddleware中間件實現(xiàn)了基于session的請求認證。通過把多個中間件組合在一起,我們可以完成更為復雜的任務,Django框架就是這么做的。
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', ]
我們稍微為大家解釋一下這些中間件的作用:
1 . CommonMiddleware - 基礎設置中間件,可以處理以下一些配置參數(shù)。
2 . SecurityMiddleware - 安全相關中間件,可以處理和安全相關的配置項。
3 . SessionMiddleware - 會話中間件。
4 . CsrfViewMiddleware - 通過生成令牌,防范跨請求份偽的造中間件。
5 . XFrameOptionsMiddleware - 通過設置請求頭參數(shù),防范點擊劫持攻擊的中間件。
在請求的過程中,上面的中間件會按照書寫的順序從上到下執(zhí)行,然后是URL解析,最后請求才會來到視圖函數(shù);在響應的過程中,上面的中間件會按照書寫的順序從下到上執(zhí)行,與請求時中間件執(zhí)行的順序正好相反。
自定義中間件
Django中的中間件有兩種實現(xiàn)方式:基于類的實現(xiàn)方式和基于函數(shù)的實現(xiàn)方式,后者更接近于裝飾器的寫法。裝飾器實際上是代理模式的應用,將橫切關注功能(與正常業(yè)務邏輯沒有必然聯(lián)系的功能,例如:身份認證、日志記錄、編碼轉換之類的功能)置于代理中,由代理對象來完成被代理對象的行為并添加額外的功能。中間件對用戶請求和響應進行攔截過濾并增加額外的處理,在這一點上它跟裝飾器是完全一致的,所以基于函數(shù)的寫法來實現(xiàn)中間件就跟裝飾器的寫法幾乎一模一樣。下面我們用自定義的中間件來實現(xiàn)用戶登錄驗證的功能。
""" middlewares.py """ from django.http import JsonResponse from django.shortcuts import redirect # 需要登錄才能訪問的資源路徑 LOGIN_REQUIRED_URLS = { '/praise/', '/criticize/', '/excel/', '/teachers_data/', } def check_login_middleware(get_resp): def wrapper(request, *args, **kwargs): # 請求的資源路徑在上面的集合中 if request.path in LOGIN_REQUIRED_URLS: # 會話中包含userid則視為已經登錄 if 'userid' not in request.session: # 判斷是不是Ajax請求 if request.is_ajax(): # Ajax請求返回JSON數(shù)據(jù)提示用戶登錄 return JsonResponse({'code': 10003, 'hint': '請先登錄'}) else: backurl = request.get_full_path() # 非Ajax請求直接重定向到登錄頁 return redirect(f'/login/?backurl={backurl}') return get_resp(request, *args, **kwargs) return wrapper
修改配置文件,激活中間件使其生效。
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', 'debug_toolbar.middleware.DebugToolbarMiddleware', 'vote.middlewares.check_login_middleware', ]
注意上面這個中間件列表中元素的順序,當收到來自用戶的請求時,中間件按照從上到下的順序依次執(zhí)行,這行完這些中間件以后,請求才會最終到達視圖函數(shù)。當然,在這個過程中,用戶的請求可以被攔截,就像上面我們自定義的中間件那樣,如果用戶在沒有登錄的情況下訪問了受保護的資源,中間件會將請求直接重定向到登錄頁,后面的中間件和視圖函數(shù)將不再執(zhí)行。在響應用戶請求的過程中,上面的中間件會按照從下到上的順序依次執(zhí)行,這樣的話我們還可以對響應做進一步的處理。
中間件執(zhí)行的順序是非常重要的,對于有依賴關系的中間件必須保證被依賴的中間件要置于依賴它的中間件的前面,就好比我們剛才自定義的中間件要放到SessionMiddleware的后面,因為我們要依賴這個中間件為請求綁定的session對象才能判定用戶是否登錄。
小結
至此,除了對用戶投票數(shù)量加以限制的功能外,這個投票應用就算基本完成了。優(yōu)勢嗎疑問,可以留言!
關注并回復:Python,可 獲得全套視頻版 Python學習教程!