溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎樣進(jìn)行Python中間件的應(yīng)用

發(fā)布時(shí)間:2021-10-26 14:40:00 來源:億速云 閱讀:174 作者:柒染 欄目:編程語言

今天就跟大家聊聊有關(guān)怎樣進(jìn)行Python中間件的應(yīng)用,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

中間件的應(yīng)用

實(shí)現(xiàn)登錄驗(yàn)證

我們繼續(xù)來完善投票應(yīng)用。在上一個(gè)章節(jié)中,我們?cè)谟脩舻卿洺晒笸ㄟ^session保留了用戶信息,接下來我們可以應(yīng)用做一些調(diào)整,要求在為老師投票時(shí)必須要先登錄,登錄過的用戶可以投票,否則就將用戶引導(dǎo)到登錄頁面,為此我們可以這樣修改視圖函數(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': '請(qǐng)先登錄'}
   return JsonResponse(data)

前端頁面在收到{'code': 401, 'message': '請(qǐng)先登錄'}后,可以將用戶引導(dǎo)到登錄頁面,修改后的teacher.html頁面的JavaScript代碼部門如下所示。

<script>
   $(() => {
       $('.comment > a').on('click', (evt) => {
           evt.preventDefault()
           let a = $(evt.target)
           $.getJSON(a.attr('href'), (json) => {
               if (json.code == 200) {
                   let span = a.next()
                   span.text(parseInt(span.text()) + 1)
               } else if (json.code == 401) {
                   location.href = '/login/?backurl=' + location.href
               } else {
                   alert(json.message)
               }
           })
       })
   })
</script>

注意:為了在登錄成功之后能夠回到剛才投票的頁面,我們?cè)谔D(zhuǎn)登錄時(shí)設(shè)置了一個(gè)backurl參數(shù),把當(dāng)前瀏覽器中的URL作為返回的頁面地址。

這樣我們已經(jīng)實(shí)現(xiàn)了用戶必須登錄才能投票的限制,但是一個(gè)新的問題來了。如果我們的應(yīng)用中有很多功能都需要用戶先登錄才能執(zhí)行,例如將前面導(dǎo)出Excel報(bào)表和查看統(tǒng)計(jì)圖表的功能都加以登錄限制,那么我們是不是需要在每個(gè)視圖函數(shù)中添加代碼來檢查session中是否包含了登錄用戶的信息呢?答案是否定的,如果這樣做了,我們的視圖函數(shù)中必然會(huì)充斥著大量的重復(fù)代碼。編程大師Martin Fowler曾經(jīng)說過:代碼有很多種壞味道,重復(fù)是最壞的一種。在Django項(xiàng)目中,我們可以把驗(yàn)證用戶是否登錄這樣的重復(fù)性代碼放到中間件中。

怎樣進(jìn)行Python中間件的應(yīng)用

Django中間件概述

中間件是安插在Web應(yīng)用請(qǐng)求和響應(yīng)過程之間的組件,它在整個(gè)Web應(yīng)用中扮演了攔截過濾器的角色,通過中間件可以攔截請(qǐng)求和響應(yīng),并對(duì)請(qǐng)求和響應(yīng)進(jìn)行過濾(簡(jiǎn)單的說就是執(zhí)行額外的處理)。通常,一個(gè)中間件組件只專注于完成一件特定的事,例如:Django框架通過SessionMiddleware中間件實(shí)現(xiàn)了對(duì)session的支持,又通過AuthenticationMiddleware中間件實(shí)現(xiàn)了基于session的請(qǐng)求認(rèn)證。通過把多個(gè)中間件組合在一起,我們可以完成更為復(fù)雜的任務(wù),Django框架就是這么做的。

Django項(xiàng)目的配置文件中就包含了對(duì)中間件的配置,代碼如下所示。

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 - 基礎(chǔ)設(shè)置中間件,可以處理以下一些配置參數(shù)。DISALLOWED_USER_AGENTS - 不被允許的用戶代理(瀏覽器)APPEND_SLASH - 是否追加/USE_ETAG - 瀏覽器緩存相關(guān)

  2. SecurityMiddleware - 安全相關(guān)中間件,可以處理和安全相關(guān)的配置項(xiàng)。SECURE_HSTS_SECONDS - 強(qiáng)制使用HTTPS的時(shí)間SECURE_HSTS_INCLUDE_SUBDOMAINS - HTTPS是否覆蓋子域名SECURE_CONTENT_TYPE_NOSNIFF - 是否允許瀏覽器推斷內(nèi)容類型SECURE_BROWSER_XSS_FILTER - 是否啟用跨站腳本攻擊過濾器SECURE_SSL_REDIRECT - 是否重定向到HTTPS連接SECURE_REDIRECT_EXEMPT - 免除重定向到HTTPS

  3. SessionMiddleware - 會(huì)話中間件。

  4. CsrfViewMiddleware - 通過生成令牌,防范跨請(qǐng)求份偽的造中間件。

  5. XFrameOptionsMiddleware - 通過設(shè)置請(qǐng)求頭參數(shù),防范點(diǎn)擊劫持攻擊的中間件。

在請(qǐng)求的過程中,上面的中間件會(huì)按照書寫的順序從上到下執(zhí)行,然后是URL解析,最后請(qǐng)求才會(huì)來到視圖函數(shù);在響應(yīng)的過程中,上面的中間件會(huì)按照書寫的順序從下到上執(zhí)行,與請(qǐng)求時(shí)中間件執(zhí)行的順序正好相反。

自定義中間件

Django中的中間件有兩種實(shí)現(xiàn)方式:基于類的實(shí)現(xiàn)方式和基于函數(shù)的實(shí)現(xiàn)方式,后者更接近于裝飾器的寫法。裝飾器實(shí)際上是代理模式的應(yīng)用,將橫切關(guān)注功能(與正常業(yè)務(wù)邏輯沒有必然聯(lián)系的功能,例如:身份認(rèn)證、日志記錄、編碼轉(zhuǎn)換之類的功能)置于代理中,由代理對(duì)象來完成被代理對(duì)象的行為并添加額外的功能。中間件對(duì)用戶請(qǐng)求和響應(yīng)進(jìn)行攔截過濾并增加額外的處理,在這一點(diǎn)上它跟裝飾器是完全一致的,所以基于函數(shù)的寫法來實(shí)現(xiàn)中間件就跟裝飾器的寫法幾乎一模一樣。下面我們用自定義的中間件來實(shí)現(xiàn)用戶登錄驗(yà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):
       # 請(qǐng)求的資源路徑在上面的集合中
       if request.path in LOGIN_REQUIRED_URLS:
           # 會(huì)話中包含userid則視為已經(jīng)登錄
           if 'userid' not in request.session:
               # 判斷是不是Ajax請(qǐng)求
               if request.is_ajax():
                   # Ajax請(qǐng)求返回JSON數(shù)據(jù)提示用戶登錄
                   return JsonResponse({'code': 10003, 'hint': '請(qǐng)先登錄'})
               else:
                   backurl = request.get_full_path()
                   # 非Ajax請(qǐng)求直接重定向到登錄頁
                   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',
]

注意上面這個(gè)中間件列表中元素的順序,當(dāng)收到來自用戶的請(qǐng)求時(shí),中間件按照從上到下的順序依次執(zhí)行,這行完這些中間件以后,請(qǐng)求才會(huì)最終到達(dá)視圖函數(shù)。當(dāng)然,在這個(gè)過程中,用戶的請(qǐng)求可以被攔截,就像上面我們自定義的中間件那樣,如果用戶在沒有登錄的情況下訪問了受保護(hù)的資源,中間件會(huì)將請(qǐng)求直接重定向到登錄頁,后面的中間件和視圖函數(shù)將不再執(zhí)行。在響應(yīng)用戶請(qǐng)求的過程中,上面的中間件會(huì)按照從下到上的順序依次執(zhí)行,這樣的話我們還可以對(duì)響應(yīng)做進(jìn)一步的處理。

中間件執(zhí)行的順序是非常重要的,對(duì)于有依賴關(guān)系的中間件必須保證被依賴的中間件要置于依賴它的中間件的前面,就好比我們剛才自定義的中間件要放到SessionMiddleware的后面,因?yàn)槲覀円蕾囘@個(gè)中間件為請(qǐng)求綁定的session對(duì)象才能判定用戶是否登錄。

看完上述內(nèi)容,你們對(duì)怎樣進(jìn)行Python中間件的應(yīng)用有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI