通俗易懂講解Json Web Token (JWT)
前言
之前只是了解JWT是對(duì)cookie和session的一種升級(jí)方案,在前后分離的項(xiàng)目中用的比較多,今天突然好奇,它到底怎么解決session共享的問題的,覺得大概明白后,總結(jié)了一下相關(guān)知識(shí)。
基于session認(rèn)證所顯露的問題
session數(shù)據(jù)默認(rèn)是保存在服務(wù)器內(nèi)存中的,而隨著認(rèn)證用戶的增多,服務(wù)端的開銷會(huì)明顯增大。
因?yàn)閟ession是保存在服務(wù)器內(nèi)存中的,在分布式的應(yīng)用上,不能保證每次都請(qǐng)求到同一臺(tái)服務(wù)器,相應(yīng)的限制了負(fù)載均衡的能力,只能通過服務(wù)器之間的session共享解決問題。
session是基于cookie來進(jìn)行用戶識(shí)別的, cookie如果被截獲,用戶就會(huì)很容易受到**跨站請(qǐng)求偽造(CSRF)**的攻擊。
組成
Token由三部分組成:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
第一部分為頭部(header),其中包含了簽名的加密算法
第二部分為載荷(payload, 類似于飛機(jī)上承載的物品),用來保存用戶的相關(guān)信息
第三部分是簽名(signature),用來驗(yàn)證token是否被篡改過
header
jwt的頭部承載兩部分信息:
- 聲明類型,這里是jwt
- 聲明簽名的加密算法 通常直接使用 HMAC SHA256
完整的頭部就像下面這樣的JSON:
{ ?'typ': 'JWT', ?'alg': 'HS256'}然后將頭部進(jìn)行base64加密(該加密是可以對(duì)稱解密的),構(gòu)成了第一部分
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
playload
包含三個(gè)部分:
- 標(biāo)準(zhǔn)中注冊(cè)的聲明
- 公共的聲明
- 私有的聲明
標(biāo)準(zhǔn)中注冊(cè)的聲明 (建議但不強(qiáng)制使用) :
iss: jwt簽發(fā)者sub: jwt所面向的用戶aud: 接收jwt的一方exp: jwt的過期時(shí)間,這個(gè)過期時(shí)間必須要大于簽發(fā)時(shí)間nbf: 定義在什么時(shí)間之前,該jwt都是不可用的.iat: jwt的簽發(fā)時(shí)間jti: jwt的唯一身份標(biāo)識(shí),主要用來作為一次性token,從而回避重放攻擊。
公共的聲明 :
公共的聲明可以添加任何的信息,一般添加用戶的相關(guān)信息或其他業(yè)務(wù)需要的必要信息。但不建議添加敏感信息,因?yàn)樵摬糠衷诳蛻舳丝山饷堋?/p>
私有的聲明 :
私有聲明是提供者和消費(fèi)者所共同定義的聲明,一般不建議存放敏感信息,因?yàn)閎ase64是對(duì)稱解密的,意味著該部分信息可以歸類為明文信息。
payload示例:
{ ?"sub": "1234567890", ?"name": "John Doe", ?"admin": true}然后將其進(jìn)行base64加密,得到Jwt的第二部分
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
signature
jwt的第三部分token簽名,它通過base64加密后的header和payload生成。
服務(wù)端將base64加密后的header和payload使用.連接組成一個(gè)字符串(頭部在前),然后通過header中聲明的簽名加密方式使用secret密鑰加密,就構(gòu)成了jwt的第三部分。
如果header和payload的內(nèi)容被修改過,生成的簽名就會(huì)是不同的(可以理解成不同內(nèi)容的哈希值不一樣),從而達(dá)到判斷token是否是被篡改過的效果。
簽名示例:
UQmqAUhUrpDVV2ST7mZKyLTomVfg7sYkEjmdDI5XF8Q
密鑰secret是保存在服務(wù)端的,服務(wù)端會(huì)根據(jù)這個(gè)密鑰進(jìn)行生成token和驗(yàn)證,需要保護(hù)好,不能泄漏。
驗(yàn)證過程
服務(wù)器應(yīng)用在接受到JWT后,會(huì)首先對(duì)頭部和載荷的內(nèi)容用同一算法再次進(jìn)行簽名。
如果服務(wù)器應(yīng)用對(duì)頭部和載荷再次以同樣方法簽名之后發(fā)現(xiàn),自己計(jì)算出來的簽名和接受到的簽名不一樣,那么就說明這個(gè)Token的內(nèi)容被篡改過,否則就完成了驗(yàn)證。
那么服務(wù)器應(yīng)用是怎么知道我們用的是哪一種算法進(jìn)行的簽名的呢?JWT的頭部中已經(jīng)用alg字段指明了我們的簽名加密算法了。
基于token的鑒權(quán)機(jī)制
- 用戶使用用戶名密碼來請(qǐng)求服務(wù)器
- 服務(wù)器進(jìn)行驗(yàn)證用戶的信息
- 服務(wù)器通過驗(yàn)證發(fā)送給用戶一個(gè)token
- 客戶端存儲(chǔ)token,并在每次請(qǐng)求時(shí)附送上這個(gè)token值
- 服務(wù)端驗(yàn)證token值,并返回?cái)?shù)據(jù)
優(yōu)點(diǎn)
- 支持跨域訪問: Cookie是不允許垮域訪問的,Token機(jī)制不基于Cookie實(shí)現(xiàn),可以跨域訪問。
- 服務(wù)端無狀態(tài),可擴(kuò)展性好: Token機(jī)制在服務(wù)端不需要存儲(chǔ)session信息,因?yàn)門oken 自身包含了所有登錄用戶的信息,服務(wù)端只需要進(jìn)行token驗(yàn)證即可。
- 更安全:Token不基于Cookie實(shí)現(xiàn),不會(huì)出現(xiàn)Cookie劫持所導(dǎo)致的安全問題。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
JS庫 Highlightjs 添加代碼行號(hào)的實(shí)現(xiàn)代碼
Highlightjs是一款優(yōu)秀的代碼高亮Js組件,可以很方便地對(duì)各種語言編寫的代碼添加語法高亮樣式。本文重點(diǎn)給大家介紹Highlightjs 添加代碼行號(hào)的實(shí)現(xiàn)代碼,需要的朋友參考下吧2017-09-09
js實(shí)現(xiàn)導(dǎo)入導(dǎo)出功能實(shí)例代碼(FileSave.js)
這篇文章主要給大家介紹了關(guān)于js實(shí)現(xiàn)導(dǎo)入導(dǎo)出功能(FileSave.js)的相關(guān)資料,FileSaver.js是在客戶端保存文件的解決方案,非常適合在客戶端上生成文件的Web應(yīng)用,需要的朋友可以參考下2023-11-11
使用JS實(shí)現(xiàn)抖音上很火的圣誕樹的示例代碼
圣誕節(jié)快到了,經(jīng)常會(huì)在抖音上刷到圣誕樹的視頻,所以本文小編給大家介紹了如何使用JS實(shí)現(xiàn)圣誕樹,文章通過代碼示例給大家介紹的非常詳細(xì),感興趣的小伙伴跟著小編一起來看看吧2023-12-12
Express代理轉(zhuǎn)發(fā)服務(wù)器實(shí)現(xiàn)
這篇文章主要為大家介紹了Express代理轉(zhuǎn)發(fā)服務(wù)器實(shí)現(xiàn)技巧詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
js使用for循環(huán)及if語句判斷多個(gè)一樣的name
這篇文章主要介紹了js使用for循環(huán)機(jī)if語句判斷多個(gè)一樣的name,此法比較實(shí)用,需要的朋友可以參考下2014-09-09
javascript封裝簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了javascript封裝簡(jiǎn)單實(shí)現(xiàn)方法,涉及javascript中方法與屬性的相關(guān)設(shè)置與使用技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08

