国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術文章
文章詳情頁

python中JWT用戶認證的實現

瀏覽:26日期:2022-07-25 10:06:26

在前后端分離開發時為什么需要用戶認證呢?原因是由于HTTP協定是不儲存狀態的(stateless),這意味著當我們透過帳號密碼驗證一個使用者時,當下一個request請求時它就把剛剛的資料忘了。于是我們的程序就不知道誰是誰,就要再驗證一次。所以為了保證系統安全,我們就需要驗證用戶否處于登錄狀態。

一、傳統方式

前后端分離通過Restful API進行數據交互時,如何驗證用戶的登錄信息及權限。在原來的項目中,使用的是最傳統也是最簡單的方式,前端登錄,后端根據用戶信息生成一個token,并保存這個token 和對應的用戶id到數據庫或Session中,接著把token 傳給用戶,存入瀏覽器 cookie,之后瀏覽器請求帶上這個cookie,后端根據這個cookie值來查詢用戶,驗證是否過期。

但這樣做問題就很多,如果我們的頁面出現了 XSS 漏洞,由于 cookie 可以被 JavaScript 讀取,XSS 漏洞會導致用戶 token 泄露,而作為后端識別用戶的標識,cookie 的泄露意味著用戶信息不再安全。盡管我們通過轉義輸出內容,使用 CDN 等可以盡量避免 XSS 注入,但誰也不能保證在大型的項目中不會出現這個問題。

在設置 cookie 的時候,其實你還可以設置 httpOnly 以及 secure項。設置 httpOnly后 cookie 將不能被 JS 讀取,瀏覽器會自動的把它加在請求的 header 當中,設置 secure的話,cookie 就只允許通過 HTTPS 傳輸。secure 選項可以過濾掉一些使用 HTTP 協議的 XSS 注入,但并不能完全阻止。

httpOnly 選項使得 JS 不能讀取到 cookie,那么 XSS 注入的問題也基本不用擔心了。但設置 httpOnly就帶來了另一個問題,就是很容易的被 XSRF,即跨站請求偽造。當你瀏覽器開著這個頁面的時候,另一個頁面可以很容易的跨站請求這個頁面的內容。因為 cookie 默認被發了出去。

另外,如果將驗證信息保存在數據庫中,后端每次都需要根據token查出用戶id,這就增加了數據庫的查詢和存儲開銷。若把驗證信息保存在session中,有加大了服務器端的存儲壓力。那我們可不可以不要服務器去查詢呢?如果我們生成token遵循一定的規律,比如我們使用對稱加密算法來加密用戶id形成token,那么服務端以后其實只要解密該token就可以知道用戶的id是什么了。不過呢,我只是舉個例子而已,要是真這么做,只要你的對稱加密算法泄露了,其他人可以通過這種加密方式進行偽造token,那么所有用戶信息都不再安全了。恩,那用非對稱加密算法來做呢,其實現在有個規范就是這樣做的,就是我們接下來要介紹的 JWT。

二、Json Web Token(JWT)

WT 是一個開放標準(RFC 7519),它定義了一種用于簡潔,自包含的用于通信雙方之間以 JSON 對象的形式安全傳遞信息的方法。JWT 可以使用 HMAC 算法或者是 RSA 的公鑰密鑰對進行簽名。它具備兩個特點:

簡潔(Compact)

可以通過URL, POST 參數或者在 HTTP header 發送,因為數據量小,傳輸速度快

自包含(Self-contained)

負載中包含了所有用戶所需要的信息,避免了多次查詢數據庫

JWT 組成

Header 頭部

頭部包含了兩部分,token 類型和采用的加密算法

{ 'alg': 'HS256', 'typ': 'JWT'}

它會使用 Base64 編碼組成 JWT 結構的第一部分,如果你使用Node.js,可以用Node.js的包base64url來得到這個字符串。------------ Base64是一種編碼,也就是說,它是可以被翻譯回原來的樣子來的。它并不是一種加密過程。

Payload 負載

負載就是存放有效信息的地方。這些有效信息包含三個部分:----標準中注冊聲明----公共的聲明----私有的聲明

公共的聲明:

公共的聲明可以添加任何的信息,一般添加用戶的相關信息或其他業務需要的必要信息.但不建議添加敏感信息,因為該部分在客戶端可解密。

私有的聲明:

私有聲明是提供者和消費者所共同定義的聲明,一般不建議存放敏感信息,因為base64是對稱解密的,意味著該部分信息可以歸類為明文信息

{ 'iss': 'lion1ou JWT', 'iat': 1441593502, 'exp': 1441594722, 'aud': 'www.example.com', 'sub': '[email protected]'}// 包括需要傳遞的用戶信息;{ 'iss': 'Online JWT Builder', 'iat': 1416797419, 'exp': 1448333419, 'aud': 'www.gusibi.com', 'sub': 'uid', 'nickname': 'goodspeed', 'username': 'goodspeed', 'scopes': [ 'admin', 'user' ] } iss: 該JWT的簽發者,是否使用是可選的; sub: 該JWT所面向的用戶,是否使用是可選的; aud: 接收該JWT的一方,是否使用是可選的; exp(expires): 什么時候過期,這里是一個Unix時間戳,是否使用是可選的; iat(issued at): 在什么時候簽發的(UNIX時間),是否使用是可選的;

其他還有:

nbf (Not Before):如果當前時間在nbf里的時間之前,則Token不被接受;一般都會留一些余地,比如幾分鐘;,是否使用是可選的; jti: jwt的唯一身份標識,主要用來作為一次性token,從而回避重放攻擊。 同樣的,它會使用 Base64 編碼組成 JWT 結構的第二部分。 Signature 簽名

前面兩部分都是使用 Base64 進行編碼的,即前端可以解開知道里面的信息。Signature 需要使用編碼后的 header 和 payload 以及我們提供的一個密鑰,然后使用 header 中指定的簽名算法(HS256)進行簽名。簽名的作用是保證 JWT 沒有被篡改過。

// 根據alg算法與私有秘鑰進行加密得到的簽名字串;// 這一段是最重要的敏感信息,只能在服務端解密;HMACSHA256( base64UrlEncode(header) + '.' + base64UrlEncode(payload), SECREATE_KEY)

三個部分通過.連接在一起就是我們的 JWT 了,它可能長這個樣子,長度貌似和你的加密算法和私鑰有關系。

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU3ZmVmMTY0ZTU0YWY2NGZmYzUzZGJkNSIsInhzcmYiOiI0ZWE1YzUwOGE2NTY2ZTc2MjQwNTQzZjhmZWIwNmZkNDU3Nzc3YmUzOTU0OWM0MDE2NDM2YWZkYTY1ZDIzMzBlIiwiaWF0IjoxNDc2NDI3OTMzfQ.PA3QjeyZSUh7H0GfE0vJaKW4LjKJuC3dVLQiY4hii8s

其實到這一步可能就有人會想了,HTTP 請求總會帶上 token,這樣這個 token 傳來傳去占用不必要的帶寬啊。如果你這么想了,那你可以去了解下 HTTP2,HTTP2 對頭部進行了壓縮,相信也解決了這個問題。

簽名的目的

最后一步簽名的過程,實際上是對頭部以及負載內容進行簽名,防止內容被竄改。如果有人對頭部以及負載的內容解碼之后進行修改,再進行編碼,最后加上之前的簽名組合形成新的JWT的話,那么服務器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的。如果要對新的頭部和負載進行簽名,在不知道服務器加密時用的密鑰的話,得出來的簽名也是不一樣的。

信息暴露

在這里大家一定會問一個問題:Base64是一種編碼,是可逆的,那么我的信息不就被暴露了嗎?

是的。所以,在JWT中,不應該在負載里面加入任何敏感的數據。在上面的例子中,我們傳輸的是用戶的User ID。這個值實際上不是什么敏感內容,一般情況下被知道也是安全的。但是像密碼這樣的內容就不能被放在JWT中了。如果將用戶的密碼放在了JWT中,那么懷有惡意的第三方通過Base64解碼就能很快地知道你的密碼了。

因此JWT適合用于向Web應用傳遞一些非敏感信息。JWT還經常用于設計用戶認證和授權系統,甚至實現Web應用的單點登錄。

token 生成好之后,接下來就可以用token來和服務器進行通訊了。

三、JWT 使用

下圖是client 使用 JWT 與server 交互過程:

python中JWT用戶認證的實現

1.這里在第三步我們得到 JWT 之后,需要將JWT存放在 client,之后的每次需要認證的請求都要把JWT發送過來。(請求時可以放到 header 的 Authorization )首先,前端通過Web表單將自己的用戶名和密碼發送到后端的接口。這一過程一般是一個HTTP POST請求。建議的方式是通過SSL加密的傳輸(https協議),從而避免敏感信息被嗅探。

2.后端核對用戶名和密碼成功后,將用戶的id等其他信息作為JWT Payload(負載),將其與頭部分別進行Base64編碼拼接后簽名,形成一個JWT。形成的JWT就是一個形同lll.zzz.xxx的字符串。

3.后端將JWT字符串作為登錄成功的返回結果返回給前端。前端可以將返回的結果保存在localStorage或sessionStorage上,退出登錄時前端刪除保存的JWT即可。

4.前端在每次請求時將JWT放入HTTP Header中的Authorization位。(解決XSS和XSRF問題)

5.后端檢查是否存在,如存在驗證JWT的有效性。例如,檢查簽名是否正確;檢查Token是否過期;檢查Token的接收方是否是自己(可選)。

6.驗證通過后后端使用JWT中包含的用戶信息進行其他邏輯操作,返回相應結果。

四、JWT 使用場景

WT的主要優勢在于使用無狀態、可擴展的方式處理應用中的用戶會話。服務端可以通過內嵌的聲明信息,很容易地獲取用戶的會話信息,而不需要去訪問用戶或會話的數據庫。在一個分布式的面向服務的框架中,這一點非常有用。

但是,如果系統中需要使用黑名單實現長期有效的token刷新機制,這種無狀態的優勢就不明顯了。

優點快速開發不需要cookieJSON在移動端的廣泛應用不依賴于社交登錄相對簡單的概念理解

缺點Token有長度限制Token不能撤銷需要token有失效時間限制(exp)

五、和Session方式存儲id的差異

Session方式存儲用戶id的最大弊病在于Session是存儲在服務器端的,所以需要占用大量服務器內存,對于較大型應用而言可能還要保存許多的狀態。一般而言,大型應用還需要借助一些KV數據庫和一系列緩存機制來實現Session的存儲。

而JWT方式將用戶狀態分散到了客戶端中,可以明顯減輕服務端的內存壓力。除了用戶id之外,還可以存儲其他的和用戶相關的信息,例如該用戶是否是管理員、用戶所在的分組等。雖說JWT方式讓服務器有一些計算壓力(例如加密、編碼和解碼),但是這些壓力相比磁盤存儲而言可能就不算什么了。具體是否采用,需要在不同場景下用數據說話。

單點登錄

Session方式來存儲用戶id,一開始用戶的Session只會存儲在一臺服務器上。對于有多個子域名的站點,每個子域名至少會對應一臺不同的服務器,例如:www.taobao.com,nv.taobao.com,nz.taobao.com,login.taobao.com。所以如果要實現在login.taobao.com登錄后,在其他的子域名下依然可以取到Session,這要求我們在多臺服務器上同步Session。使用JWT的方式則沒有這個問題的存在,因為用戶的狀態已經被傳送到了客戶端。

六、總結

JWT的主要作用在于:(一)可附帶用戶信息,后端直接通過JWT獲取相關信息。(二)使用本地保存,通過HTTP Header中的Authorization位提交驗證。

七、附加,python使用JWT

python 中djagno rest framework要使用jwt,可以使用以下這個模塊:githubs文檔有使用說明https://github.com/GetBlimp/django-rest-framework-jwt

pip install djangorestframework-jwt

不是使用django的話,我們可以使用 pyjwt:https://github.com/jpadilla/pyjwt/使用比較方便,下邊是我在應用中使用的例子:

import jwtimport time# 使用 sanic 作為restful api 框架 def create_token(request): grant_type = request.json.get(’grant_type’) username = request.json[’username’] password = request.json[’password’] if grant_type == ’password’: account = verify_password(username, password) elif grant_type == ’wxapp’: account = verify_wxapp(username, password) if not account: return {} payload = { 'iss': 'gusibi.com', 'iat': int(time.time()), 'exp': int(time.time()) + 86400 * 7, 'aud': 'www.gusibi.com', 'sub': account[’_id’], 'username': account[’username’], 'scopes': [’open’] } token = jwt.encode(payload, ’secret’, algorithm=’HS256’) return True, {’access_token’: token, ’account_id’: account[’_id’]} def verify_bearer_token(token): # 如果在生成token的時候使用了aud參數,那么校驗的時候也需要添加此參數 payload = jwt.decode(token, ’secret’, audience=’www.gusibi.com’, algorithms=[’HS256’]) if payload: return True, token return False, token

到此這篇關于python中JWT用戶認證的實現的文章就介紹到這了,更多相關python JWT用戶認證內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Python 編程
相關文章:
主站蜘蛛池模板: 国产好片无限资源 | 国产欧美精品综合一区 | 国产精品免费看久久久香蕉 | 中文字幕一区二区三区在线观看 | 久草久草视频 | 国产片久久 | 精品国产一区二区三区久久 | 国产精品自拍在线 | 国产a网站| 亚洲综合网在线观看 | 欧美成人区 | 精品精品国产高清a毛片 | 日本女人www | 免费一级 一片一毛片 | 玖草在线播放 | 成年女人免费观看视频 | 国产younv真实 | 国产免费一级片 | 国产精品久久久久亚洲 | 成人精品久久 | 国产精品毛片在线大全 | 久久久久久亚洲精品影院 | 国产欧美一区二区精品久久久 | 欧美一级香蕉毛片 | 日韩免费看片 | 久久久久毛片成人精品 | 日韩成人中文字幕 | 68久久久久欧美精品观看 | 手机午夜看片 | 精品国产_亚洲人成在线高清 | 韩国美女激情视频一区二区 | 日韩欧美亚洲中字幕在线播放 | 亚洲黄色小视频 | 国产aⅴ一区二区三区 | 精品国产a | 亚洲一区不卡 | 色综合久久久 | 久久aa毛片免费播放嗯啊 | 日本三级韩国三级在线观看a级 | 亚洲精品国产手机 | 67194在线午夜亚洲 |