更新時(shí)間:2023-03-16 來(lái)源:黑馬程序員 瀏覽量:
JSON Web Token(JWT)是一種使用JSON格式傳遞數(shù)據(jù)的網(wǎng)絡(luò)令牌技術(shù),它是一個(gè)開放的行業(yè)標(biāo)準(zhǔn)(RFC 7519),它定義了一種簡(jiǎn)潔的、自包含的協(xié)議格式,用于在通信雙方傳遞json對(duì)象,傳遞的信息經(jīng)過(guò)數(shù)字簽名可以被驗(yàn)證和信任,它可以使用HMAC算法或使用RSA的公鑰/私鑰對(duì)來(lái)簽名,防止內(nèi)容篡改。官網(wǎng):https://jwt.io/
使用JWT可以實(shí)現(xiàn)無(wú)狀態(tài)認(rèn)證,那什么是無(wú)狀態(tài)認(rèn)證?
傳統(tǒng)的基于session的方式是有狀態(tài)認(rèn)證,用戶登錄成功將用戶的身份信息存儲(chǔ)在服務(wù)端,這樣加大了服務(wù)端的存儲(chǔ)壓力,并且這種方式不適合在分布式系統(tǒng)中應(yīng)用。
如下圖,當(dāng)用戶訪問應(yīng)用服務(wù),每個(gè)應(yīng)用服務(wù)都會(huì)去服務(wù)器查看session信息,如果session中沒有該用戶則說(shuō)明用戶沒有登錄,此時(shí)就會(huì)重新認(rèn)證,而解決這個(gè)問題的方法是Session復(fù)制、Session黏貼。
如果是基于令牌技術(shù)在分布式系統(tǒng)中實(shí)現(xiàn)認(rèn)證則服務(wù)端不用存儲(chǔ)session,可以將用戶身份信息存儲(chǔ)在令牌中,用戶認(rèn)證通過(guò)后認(rèn)證服務(wù)頒發(fā)令牌給用戶,用戶將令牌存儲(chǔ)在客戶端,去訪問應(yīng)用服務(wù)時(shí)攜帶令牌去訪問,服務(wù)端從jwt解析出用戶信息。這個(gè)過(guò)程就是無(wú)狀態(tài)認(rèn)證。
1、jwt基于json,非常方便解析。
2、可以在令牌中自定義豐富的內(nèi)容,易擴(kuò)展。
3、通過(guò)非對(duì)稱加密算法及數(shù)字簽名技術(shù),JWT防止篡改,安全性高。
4、資源服務(wù)使用JWT可不依賴認(rèn)證服務(wù)即可完成授權(quán)。
缺點(diǎn):
1、JWT令牌較長(zhǎng),占存儲(chǔ)空間比較大。
下邊是一個(gè)JWT令牌的示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsicmVzMSJdLCJ1c2VyX 25hbWUiOiJ6aGFuZ3NhbiIsInNjb3BlIjpbImFsbCJdLCJleHAiOjE2NjQyNTQ2NzI sImF1dGhvcml0aWVzIjpbInAxIl0sImp0aSI6Ijg4OTEyYjJkLTVkMDUtNGMxNC1iY mMzLWZkZTk5NzdmZWJjNiIsImNsaWVudF9pZCI6ImMxIn0.wkDBL7roLrvdBG2oGnX eoXq-zZRgE9IVV2nxd-ez_oA
JWT令牌由三部分組成,每部分中間使用點(diǎn)(.)分隔,比如:xxxxx.yyyyy.zzzzz
頭部包括令牌的類型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA) 一個(gè)例子如下:
下邊是Header部分的內(nèi)容
{ "alg": "HS256", "typ": "JWT" }
將上邊的內(nèi)容使用Base64Url編碼,得到一個(gè)字符串就是JWT令牌的第一部分。
第二部分是負(fù)載,內(nèi)容也是一個(gè)json對(duì)象,它是存放有效信息的地方,它可以存放jwt提供的信息字段,比如:iss(簽發(fā)者),exp(過(guò)期時(shí)間戳), sub(面向的用戶)等,也可自定義字段。
此部分不建議存放敏感信息,因?yàn)榇瞬糠挚梢越獯a還原原始內(nèi)容。
最后將第二部分負(fù)載使用Base64Url編碼,得到一個(gè)字符串就是JWT令牌的第二部分。
一個(gè)例子:
{ "sub": "1234567890", "name": "456", "admin": true }
第三部分是簽名,此部分用于防止jwt內(nèi)容被篡改。
這個(gè)部分使用base64url將前兩部分進(jìn)行編碼,編碼后使用點(diǎn)(.)連接組成字符串,最后使用header中聲明的簽名算法進(jìn)行簽名。
一個(gè)例子:
HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
base64UrlEncode(header):jwt令牌的第一部分。
base64UrlEncode(payload):jwt令牌的第二部分。
secret:簽名所使用的密鑰。
第三部分使用簽名算法對(duì)第一部分和第二部分的內(nèi)容進(jìn)行簽名,常用的簽名算法是 HS256,常見的還有md5,sha 等,簽名算法需要使用密鑰進(jìn)行簽名,密鑰不對(duì)外公開,并且簽名是不可逆的,如果第三方更改了內(nèi)容那么服務(wù)器驗(yàn)證簽名就會(huì)失敗,要想保證驗(yàn)證簽名正確必須保證內(nèi)容、密鑰與簽名前一致。
從上圖可以看出認(rèn)證服務(wù)和資源服務(wù)使用相同的密鑰,這叫對(duì)稱加密,對(duì)稱加密效率高,如果一旦密鑰泄露可以偽造jwt令牌。
JWT還可以使用非對(duì)稱加密,認(rèn)證服務(wù)自己保留私鑰,將公鑰下發(fā)給受信任的客戶端、資源服務(wù),公鑰和私鑰是配對(duì)的,成對(duì)的公鑰和私鑰才可以正常加密和解密,非對(duì)稱加密效率低但相比對(duì)稱加密非對(duì)稱加密更安全一些。