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