jwt token注销_辩证的眼光搞懂 JWT 这个知识点
什么是 JWT
概念
JSON Web Token(簡稱 JWT)是目前最流行的跨域認證解決方案。
JWT 原理
JWT 組成
JWT 由三部分組成:Header,Payload,Signature 三個部分組成,并且最后由.拼接而成。
Header
Header 部分是一個 JSON 對象,描述 JWT 的元數據,通常是下面的樣子。
{"alg": "HS256",
"typ": "JWT"
}
上面代碼中,alg 屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ 屬性表示這個令牌(token)的類型(type),JWT 令牌統一寫為 JWT。
最后將上面的 JSON 對象使用 Base64URL 算法轉成字符串。
Payload
Payload 中由 Registered Claim 以及需要通信的數據組成。它也是 JSON 格式,另外這些數據字段也叫 Claim。JWT 規定了7個官方字段如下
iss (issuer):簽發人exp (expiration time):過期時間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時間
iat (Issued At):簽發時間
jti (JWT ID):編號
除了官方的字段外你也可以自定義一些字段,比如 user_id,name 等
Registered Claim 中比較重要的是 "exp" Claim 表示過期時間,在用戶登錄時會設置過期時間,用于后面過期校驗。
const payload = {// 表示 jwt 創建時間
iat: 1532135735,
// 表示 jwt 過期時間
exp: 1532136735,
// 用戶 id,用以通信
user_id: 123456
}
Signature
Signature 部分是對前兩部分的簽名,防止數據篡改。
首先,需要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。
// 由 HMACSHA256 算法進行簽名,secret 不能外泄const sign = HMACSHA256(base64.encode(header) + '.' + base64.encode(payload), secret)
// jwt 由三部分拼接而成
const jwt = base64.encode(header) + '.' + base64.encode(payload) + '.' + sign
算出簽名以后,把 Header、Payload、Signature 三個部分拼成一個字符串,每個部分之間用"點"(.)分隔,。
JWT 校驗原理
圖片總是更清晰:
通過前面講解的 jwt 生成規則,jwt 前兩部分是對 header 以及 payload 的 base64 編碼。?當服務器收到客戶端的 token 后,解析前兩部分得到 header 以及 payload,并使用 header 中的算法與 服務端本地私有 secret 進行簽名,判斷與 jwt 中攜帶的簽名是否一致。
編碼擴展知識
base64
由于 ASCII 碼成為了國際標準,所以我們要把其它字符轉成 ASCII 就要用到 base64。
utf-8 -> base64(編碼) -> ASCII
ASCII -> base64(解碼) -> utf-8這樣就可以讓只支持 ASCII 的計算機支持 utf-8 了。
base64 幾個特點 :2進制的;要比源數據多33%;常用于郵件;?= 號的個數是由 /3 的余數來決定的,最多能有 2 個 = 號;
主要用于初步的加密(非明文可見)和安全的網絡傳輸。
UrlEncode
例子:www.baidu.com?a=nihao
上面的例子可以看出 a 的值是你好
如果要把 a 的值換成 “=” 字符呢?這樣嗎:www.baidu.com?a== ,肯定不行啦,“=” 是特殊字符
所以把 “=” UrlEncode后 “%3d”
www.baidu.com?a=%3d
服務器拿到 a 解碼得到 “=”
所以說 url 是限制性編碼
看完這兩個編碼應該明白為什么上面base64.encode這種格式轉換。JWT ?作為一個令牌(token),有些場合可能會放到 URL(比如 www.inode.club/?token=xxx)
JWT 與 Session 對比
有無狀態對比
Session
Session 是一種記錄服務器和客戶端會話狀態的機制,需要在數據庫或者 Redis 中保存用戶信息和token信息,所以它是有狀態的。
JWT 看完了前面的 JWT 結構和 JWT 校驗原理,在后端并不需要存儲數據,直接通過私有密鑰驗證就可以了。
當有這樣的一個需求,一家公司下同時關聯了多個業務,A業務網站,B業務網站,但是現在要求用戶在A網站登陸過,再訪問B網站的時候能夠自動登陸,JWT 就可以很快的實現這個需求,把 JWT 直接存儲在前端,后端只要校驗 JWT 就可以了。
注:這個需求用 session 也是可以實現的,只是會存儲狀態,查詢存儲,沒有 JWT 方便而已。
適用場景對比
郵箱驗證
很多網站在注冊成功后添加了郵箱驗證功能,功能實現:用戶注冊成功后,完善郵箱,服務端會給用戶郵箱發一個鏈接,用戶點開鏈接校驗成功,這個功能使用 JWT 是個不錯的選擇。
// 把郵箱以及用戶id綁定在一起,設置生效時間const code = jwt.sign({ email, userId }, secret, { expiresIn: 60 * 30 })
// 在此鏈接校驗驗證碼
const link = `https://www.inode.club/code=${code}`
做那些短期的驗證需求(強烈推薦的場景)
比如在?BFF?層,用 JWT 去驗證傳遞一些數據還是不錯的選擇,可以把有效時間設置的短一些,過期了就需要重新去請求,我這么直接表述你可能還不太懂,舉個現實生活中的例子。
我們上學的時候,有班主任和學科老師這兩個概念,有一天你想請假,你需要先去找班主任開一個請假條,然后拿去給你的班主任簽完字之后,你會將請假條交給你的學科課教師,學科教師確認簽字無誤后,把請假條收了,并在請假記錄表中作出了相應記錄。
上面的例子中,“請假申請單”就是JWT中的payload,領導簽字就是base64后的數字簽名,領導是issuer,“學科教師的老王”即為JWT的audience,audience需要驗證班主任簽名是否合法,驗證合法后根據payload中請求的資源給予相應的權限,同時將JWT收回。
放到一些系統集成的應用場景中,例如我前面說的?BFF?中其實 JWT 更適合一次性操作的認證:
服務 B 你好, 服務 A 告訴我,我可以操作 , 這是我的憑證(即 JWT )
在這里,服務 A 負責認證用戶身份(類似于上例班主任批準請假),并頒布一個很短過期時間的JWT給瀏覽器(相當于上例的請假單),瀏覽器(相當于上例請假的我們)在向服務 B 的請求中帶上該 JWT,則服務 B(相當于上例的任課教師)可以通過驗證該 JWT 來判斷用戶是否有權限執行該操作。通過這樣,服務 B 就成為一個安全的無狀態的服務。
個人還是認為 JWT 更適合做一些一次性的安全認證,好多其他場景考慮多了之后又做回了 session,傳統的 cookie-session 機制工作得更好,但是對于一次性的安全認證,頒發一個有效期極短的JWT,即使暴露了危險也很小。上面的郵箱驗證其實也是一次性的安全認證。
跨域認證
因為 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服務而不需要擔心跨域資源共享問題(CORS)。JWT 確實是跨域認證的一個解決方案,但是對于跨域場景時要注意一點。?客戶端收到服務器返回的 JWT,可以儲存在 Cookie 里面,也可以儲存在 localStorage。
此后,客戶端每次與服務器通信,都要帶上這個 JWT。你可以把它放在 Cookie 里面自動發送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請求的頭信息Authorization字段里面。
Authorization: Bearer另一種做法是,跨域的時候,JWT 就放在 POST 請求的數據體里面。
跨域知識擴展
跨域這兩個字就像一塊狗皮膏藥一樣黏在每一個開發者身上,無論你在工作上或者面試中無可避免會遇到這個問題。為了應付面試,我們每次都隨便背幾個方案。但是如果突然問你為什么會有跨域這個問題出現??...停頓幾秒,這里只是普及一下,知道的可以忽略掉。
推薦一篇很棒的跨域文章:https://segmentfault.com/a/1190000015597029
登陸驗證
登陸驗證:不需要控制登錄設備數量以及注銷登陸情況,無狀態的 jwt 是一個不錯的選擇。具體實現流程,可以看上文中的校驗原理,校驗原理使用的登陸驗證例子。
當需求中出現控制登陸設備數量,或者可以注銷掉用戶時,可以考慮使用原有的 session 模式,因為針對這種登陸需求,需要進行的狀態存儲對 jwt 添加額外的狀態支持,增加了認證的復雜度,此時選用 session 是一個不錯的選擇。?針對上面的特殊需求,可能也有小伙伴仍喜歡使用 jwt ,補充一下特殊案例
注銷登陸
用戶注銷時候要考慮 token 的過期時間。
- session: 只需要把 user_id 對應的 token 清掉即可 ;
- jwt: 使用 redis,需要維護一張黑名單,用戶注銷時把該 token 加入黑名單,過期時間與 jwt 的過期時間保持一致。
用戶登陸設備控制
session: 使用 sql 類數據庫,維護一個用戶驗證token表,每次登陸重置表中 token 字段,每次請求需要權限接口時,根據 token 查找 user_id(也可以使用 redis 維護 token 數據的存儲)
jwt: 假使使用 sql 類數據庫,維護一個用戶驗證token表,表中添加 token 字段,每次登陸重置 token 字段,每次請求需要權限接口時,根據 jwt 獲取 user_id,根據 user_id 查用戶表獲取 token 判斷 token 是否一致。(也可以使用 redis 維護 token 數據的存儲)
適合做那些事來講的,其實也就是針對JWT的優勢來說的,還有一些辯證性的理解。接下來說說 JWT 的缺點。
JWT 注意事項(缺點)
缺點與優勢都知道了,我想怎么選就看你自己了。
總結
本文對 JWT 進行的一個辯證的講解,優勢和缺點,以及個人認為合適的適用場景,JWT 并不是銀彈,是否采用 JWT,一定要多考慮一下業務場景。希望本文讓小伙伴們對 JWT 認識的更好些。
?? 看完三件事
大家好,我是koala,如果你覺得這篇內容對你挺有啟發,我想邀請你幫我三個小忙:
點個【在看】,或者分享轉發,讓更多的人也能看到這篇內容
關注公眾號【程序員成長指北】,不定期分享原創&精品技術文章。
添加微信【?coder_qi?】。加入程序員成長指北公眾號交流群。
“在看轉發”是最大的支持
總結
以上是生活随笔為你收集整理的jwt token注销_辩证的眼光搞懂 JWT 这个知识点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: datatable 创建列赋值_Data
- 下一篇: hough变换检测圆周_hough变换原