Python?web框架實現(xiàn)增加BasicAuth認證詳解
上一篇文章,我們已經(jīng)為框架定義了【響應對象】,該框架不僅可以獲取客戶端上傳的報文信息,還能生成一些簡單信息,如自定義響應頭等等。今天我們再次完善一下該框架,給框架增加權(quán)限驗證的功能,給框架加上一個BasicAuth
的方法。
本篇文章所依賴的環(huán)境為:
本次代碼已經(jīng)放到了gitee
上:gitee.com/pdudo/golearn/tree/master/python/webFramework
什么是http BashAuth
在日常生活或者工作中,你是否見到過這樣的頁面呢?
當我們打開窗口,網(wǎng)頁并不是里面加載出來的,而是彈出了一個輸入框,讓我們輸入其用戶名和密碼,輸入后待服務器驗證通過后,才開始展現(xiàn)實際的網(wǎng)頁內(nèi)容。這個就是BashAuth
了,全稱為: Basic access authentication
,也稱基本認證。是一種極其簡單http
協(xié)議身份驗證方式。BashAuth
認證的方式是通過請求頭來發(fā)送和校驗的,而非我們熟知的cookie
、token
等。
還有一點需要注意,這里所展現(xiàn)的輸入框,其實是瀏覽器底層拆解協(xié)議所支持的。
BasicAuth認證底層原理
BasicAuth
使用的http
協(xié)議進行身份驗證的,所以會將身份信息攜帶在請求頭中進行傳輸。
第一步: 用戶在第一次進行瀏覽器請求頁面的時候,不會攜帶認證信息,此時服務器接接收信息后,判斷報文中請求頭沒有WWW-Authenticate
,此時會返回客戶端報文,其中需要將報文響應狀態(tài)碼為401
,響應頭新增一個key
為WWW-Authenticate
,值為realm
加上請求域,做法是為了避免和其他URL
相沖突。所以響應核心報文為:
HTTP/1.0 401 Unauthorized
WWW-Authenticate: Basic realm="pdudo sites"
其中狀態(tài)碼為401
代表客戶端錯誤,指的是需要身份驗證,WWW-Authenticate
響應頭的值為Basic realm="pdudo sites"
,Basic
代表驗證的模式,realm
代表請求域,請求域是為了和其他URL
相沖突。
第二步: 當瀏覽器接收到該報文后,會判斷其狀態(tài)碼為401
并且請求頭中有key
為WWW-Authenticate
,此時便會彈出輸入框,讓用戶輸入信息以便服務器校驗。
輸入之后,不是直接發(fā)送給服務器,而是會根據(jù)服務器發(fā)送的驗證模式進行校驗,如basic
,加入客戶端發(fā)送的報文如下:
GET /index HTTP/1.1
HTTP_AUTHORIZATION: Basic cGR1ZG86anVlamlu
其中Get
代表請求方式,/index
表示請求路徑,HTTP/1.1
是http
的版本。請求頭HTTP_AUTHORIZATION
表示驗證數(shù)據(jù),Basic
是驗證方式,cGR1ZG86anVlamlu
表示用戶名:密碼
,只不過瀏覽器使用base64
進行編碼了而已。
第三步: 服務器在接收到報文后,發(fā)現(xiàn)有HTTP_AUTHORIZATION
,則會使用base64
解碼,發(fā)現(xiàn)客戶端上傳的數(shù)據(jù)為pdudo:juejin
,以:
為分割,前者是用戶名,后則是密碼。當驗證通過后,進行發(fā)送其他信息,若驗證未通過,則重復第一步。
將BasicAuth認證添加到框架中
我們已經(jīng)知曉了BasicAuth
認證的底層原理,所以可以開始修改我們的框架了,我們將其代碼寫到上一篇所述的response
類中,代碼如下:
def basicAuth(self): if "HTTP_AUTHORIZATION" not in self.response: return None,None,"HTTP_AUTHORIZATION request header not found" else: originalVal = self.response["HTTP_AUTHORIZATION"] types = originalVal.split(" ")[0] values = originalVal.split(" ")[1] if types == "Basic": userAndPasswd = base64.b64decode(values).decode() user = userAndPasswd.split(":")[0] passwd = userAndPasswd.split(":")[1] return user,passwd,None else: return None, None, "HTTP_AUTHORIZATION request error,unrecognized type: %s " %(types)
當客戶端函數(shù)調(diào)用basicAuth
時,服務器檢查客戶端http
報文中,是否有HTTP_AUTHORIZATION
,如果沒有,則直接返回HTTP_AUTHORIZATION request header not found
。
若請求頭有該key
,則將其抓出來存儲到originalVal
中,它的值類似于: Basic cGR1ZG86anVlamlu
,前者是認證類型,后者是加密后字符串,所以我們需要分開將其取出來,存到types
和values
中,再判斷types
是否是Basic
,如果是我們使用base64
進行解密,解密后的值類似于pdudo:juejin
,以冒號(:
)隔開,前者為用戶名,后者為密碼,所以我們需要將字符串按照:
進行拆分,前者保存到user
中,后者保存到passwd
中,最后將其數(shù)據(jù)給函數(shù)。
那當?shù)谝徊綑z查請求頭沒有HTTP_AUTHORIZATION
或者用戶名密碼不對,應該如何返回呢? 這個需要用戶在函數(shù)中進行調(diào)用即可,例如:
@myWeb.routes(path="/index",methods="all",regular=False) def index(r): username, password , isok = r.basicAuth() if isok != None or username != "pdudo" or password != "juejin": r.set_headers("WWW-Authenticate","Basic realm="pdudo sites"") r.status_code(401) return return "123"
上述代碼,使用我們自己編寫的myWeb
框架,定義了一個路由/index
,其方法為Get
或者Post
,regular=False
則不使用正則路由,在函數(shù)中,通過r.basicAuth()
來獲取客戶端上傳的用戶名密碼,當用戶名不等于pdudo
或者密碼不等于juejin
或者解析失敗的時候,會將響應狀態(tài)碼定義為401
,并且設置響應頭,key
為WWW-Authenticate
,值為Basic realm="pdudo sites"
。
框架功能測試
這里就不貼myWeb.py
的代碼了,太長了,大家可以去gitee
上看,這里貼一下main.py
代碼:
import myweb @myweb.routes(path="/index",methods="all",regular=False) def index(r): username,password,isok = r.basicAuth() print("username:",username,"passwd:",password) if isok != None or username != "pdudo" or password !="juejin": r.set_headers("WWW-Authenticate","Basic realm=\"pdudo sites\"") r.status_code(401) return return "123" def main(): myweb.run("",8888) if __name__ == '__main__': main()
為了方便,我將每次獲取到的數(shù)據(jù),都打印一下,方便待會查看數(shù)據(jù)。
執(zhí)行代碼后,打開瀏覽器輸入http://pdudo.juejin.cn:8888/index
,當彈出框后,我們第一個故意輸錯,第二次才輸正確:
我們查看服務器日志,如下:
一共收到了3次,第一個輸出后,并沒有攜帶報文,被擋回來了,所以用戶名和密碼都為None
,第二次則是密碼輸入不正確被擋回來了,第三次輸入正確,成功得到數(shù)據(jù)123
。
總結(jié)
本篇文章,我們介紹了一個極其古老的認證方式: BashAuth
, 它是通過請求頭來發(fā)送數(shù)據(jù)和驗證的。接著我們了解了一下其認證過程,其中最常用的是類型是Basic
,它表示將數(shù)據(jù)進行base64
編碼后傳輸,注意是編碼,不是加密。所以在使用該功能的時候,最好配合https
使用,以便被抓包后破解。 最后將其添加到我們的web
框架myWeb.py
中。
到此這篇關(guān)于Python web框架實現(xiàn)增加BasicAuth認證詳解的文章就介紹到這了,更多相關(guān)Python增加BasicAuth認證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python 實現(xiàn)求解字符串集的最長公共前綴方法
今天小編就為大家分享一篇python 實現(xiàn)求解字符串集的最長公共前綴方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-07-07Pandas 對Dataframe結(jié)構(gòu)排序的實現(xiàn)方法
下面小編就為大家分享一篇Pandas 對Dataframe結(jié)構(gòu)排序的實現(xiàn)方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04如何使用Python對NetCDF數(shù)據(jù)做空間相關(guān)分析
這篇文章主要介紹了如何使用Python對NetCDF數(shù)據(jù)做空間相關(guān)分析,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下2021-04-04Python處理RSS、ATOM模塊FEEDPARSER介紹
這篇文章主要介紹了Python處理RSS、ATOM模塊FEEDPARSER介紹,本文只是做個入門級的簡潔介紹,需要的朋友可以參考下2015-02-02Python圖片視頻超分模型RealBasicVSR的使用教程
這篇文章主要和大家分享一個有意思的模型:RealBasicVSR。這個模型可以實現(xiàn)圖片或視頻的超分處理,感興趣的小伙伴可以跟隨小編一起學習一下2022-05-05python中類的輸出或類的實例輸出為<__main__類名 object at xxxx>這種形式的原因
在本篇文章里小編給大家分享了關(guān)于python中類的輸出或類的實例輸出為何是<__main__類名 object at xxxx>這種形式,需要的朋友們可以參考下。2019-08-08Python?tkinter中l(wèi)abel控件動態(tài)改變值問題
這篇文章主要介紹了Python?tkinter中l(wèi)abel控件動態(tài)改變值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01