<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你可能沒那么了解 JWT

          共 7249字,需瀏覽 15分鐘

           ·

          2021-11-04 03:47

          點擊關(guān)注公眾號,Java干貨及時送達

          0)前言

          最近在開發(fā)一個統(tǒng)一認證服務,涉及到 OIDC 協(xié)議,其中授權(quán)碼模式所頒發(fā)的 id_token 使用的是 JWT ( JSON Web Token ) ,因為這次使用的庫的默認簽名算法和以往不同,所以特地去翻閱了 JWT 的 RFC 文檔( RFC 7519[1] ),一番閱讀后發(fā)現(xiàn)原來對 JWT 的認知只停留在表面,還有更多深層的內(nèi)容是不知道的。

          1)我們最常使用的 JWT

          每次提到無狀態(tài)的 JWT 時相信都會看到另一種基于 Session 的用戶認證方案介紹,這里也不例外,Session 的認證流程通常會像這樣:

          這種方案有一些缺點:

          • 需要從內(nèi)存或數(shù)據(jù)庫里存取 session 數(shù)據(jù)
          • 擴展性差,對于分布式應用,需要實現(xiàn) session 數(shù)據(jù)共享

          JWT 正好可以解決這些問題:

          JWT 的魔法很簡單,將需要使用到的用戶數(shù)據(jù)等信息放入 JWT 里面,每次請求都會攜帶上,只要保證密鑰不泄露,JWT 就無法偽造。

          一個簡單的 JWT 示例如下:

          eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMDIxLTEwLTI0IDAwOjAwOjAwIiwibmFtZSI6InRvZ2V0dG95b3UifQ.XdF46NflSUjnt-adAc6rNZEXI1OD6nxtwGuhz9qkxUA

          jwt.io[2] 這個網(wǎng)站相信沒有人不知道了,把上面的 JWT 復制粘貼到網(wǎng)站中

          可以看出 JWT 以不同顏色區(qū)分,兩個小數(shù)點隔開,分為了三部分

          ① Header(頭部):JSON 對象,描述 JWT 的元數(shù)據(jù)。其中 alg 屬性表示簽名的算法(algorithm),默認是 HMAC SHA256(寫成 HS256);typ 屬性表示這個令牌(token)的類型(type),統(tǒng)一寫為 JWT

          ② Payload(載荷):JSON 對象,存放實際需要傳遞的數(shù)據(jù),支持自定義字段

          ③ Signature(簽名):這部分就是 JWT 防篡改的精髓,其值是對前兩部分 base64UrlEncode 后使用指定算法簽名生成,以默認 HS256 為例,指定一個密鑰(secret),就會按照如下公式生成:

          HMACSHA256(
          ?base64UrlEncode(header)?+?"."?+?base64UrlEncode(payload),
          ?secret,
          )

          到這里,大多數(shù)人對 JWT 的認知應該是停留在此了,日常使用也已經(jīng)足夠,但你想更深入了解 JWT 的話,那你就得知道 JOSE

          2)JOSE 規(guī)范

          什么是 JOSE ,它和 JWT 之間又有什么關(guān)系呢。

          JOSE 全稱 JSON Object Signing and Encryption ( RFC 7165[3] , RFC 7520[4] ),它定義了一系列的標準,用來規(guī)范網(wǎng)絡傳輸過程中使用 JSON 的方式,我們上面一直說的 JWT 其實是 JOSE 體系之一。

          其中 JWT 又可分為 JWS 和 JWE 兩種不同的實現(xiàn),我們大部分日常所使用的,所說的 JWT 其實應該屬于 JWS 。 為什么這么說,請看下文。

          3)JWA 和 JWS 以及 JWK

          JWA 的全稱是 JSON Web Algorithms ( RFC 7518[5] ) ,字如其名, JOSE 體系中涉及到的所有算法就是它來定義的,比如通用算法有 Base64-URL 和 SHA,簽名算法有 HMAC,RSA 和 Elliptic Curve(EC 橢圓曲線),本文不會深入到算法原理(我也不懂),只是想讓你知道 JWA 是做什么的。我們上面的 JWT 例子中第一部分 Header 有個 alg 屬性,其值是 HS256 ,也就是 HMAC + SHA256 算法。

          說了那么多,好像都沒有正式介紹過 JWS 。JWS 的全稱是 JSON Web Signature ( RFC 7515[6] ) ,它的核心就是簽名,保證數(shù)據(jù)未被篡改,而檢查簽名的過程就叫做驗證。更通俗的理解,就是對應前面提到的 JWT 的第三部分 Signature ,所以我才會說我們?nèi)粘K褂玫?JWT 都是 JWS 。

          通常在客戶端-服務端模式中,JWS 使用 JWA 提供的 HS256 算法加上一個密鑰即可,這種方式嚴格依賴密鑰,但在分布式場景,可能多個服務都需要驗證 JWT ,若要在每個服務里面都保存密鑰,那么安全性將會大打折扣,要知道,密鑰一旦泄露,任何人都可以隨意偽造 JWT 。

          解決辦法就是使用非對稱加密算法 RSA ,RSA 有兩把鑰匙,一把公鑰,一把私鑰,可以使用私鑰簽發(fā)(簽名分發(fā)) JWT ,使用公鑰驗證 JWT ,公鑰是所有人都可以獲取到的。這樣一來,就只有認證服務保存著私鑰,進行簽發(fā),其他服務只能驗證。

          如下是一個使用 RS256 ( RSA + SHA256 ) 算法生成的 JWT :

          eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjF6aXlIVG15M184MDRDOU1jUENHVERmYWJCNThBNENlZG9Wa3VweXdVeU0ifQ.eyJqdGkiOiIzWUJ5eWZ2TDB4b01QNXdwTXVsZ0wiLCJzdWIiOiI2MDE5NDI5NjgwMWRjN2JjMmExYjI3MzUiLCJpYXQiOjE2MTI0NDQ4NzEsImV4cCI6MTYxMzY1NDQ3MSwic2NvcGUiOiJvcGVuaWQgZW1haWwgbWVzc2FnZSIsImlzcyI6Imh0dHBzOi8vc3RlYW0tdGFsay5hdXRoaW5nLmNuL29pZGMiLCJhdWQiOiI2MDE5M2M2MTBmOTExN2U3Y2IwNDkxNTkifQ.cYyZ6buwAjp7DzrYQEhvz5rvUBhkv_s8xzuv2JHgzYx0jbqqsWrA_-gufLTFGmNkZkZwPnF6ktjvPHFT-1iJfWGRruOOMV9QKPhk0S5L2eedtbKJU6XIEkl3F9KbOFwYM53v3E7_VC8RBj5IKqEY0qd4mW36C9VbS695wZlvMYnmXhIopYsd5c83i39fLBF8vEBZE1Rq6tqTQTbHAasR2eUz1LnOqxNp2NNkV2dzlcNIksSDbEGjTNkWceeTWBRtFMi_o9EWaHExdm5574jQ-ei5zE4L7x-zfp9iAe8neuAgTsqXOa6RJswhyn53cW4DwWg_g26lHJZXQvv_RHZRlQ

          把它復制到 jwt.io 上面看看

          注意我綠色框選中的地方,里面是一段 JSON ,我們把它刪掉,看看輸入框的提示信息

          這里提示了,里面是填寫公鑰格式(通常為 PEM)或者 JWK (我們說過 RSA 算法是使用私鑰簽發(fā) JWT,公鑰進行驗證),剛剛我們刪掉的是一段 JSON,所以必然不是公鑰格式,那是 JWK 嗎?

          當然是,JWK 的全稱是 JSON Web Key ( RFC 7517[7] ) ,它就是一個 JSON ,JWK 就是用 JSON 來表示密鑰(JSON 字段因密鑰類型而異)。例如剛才刪除的 JWK :

          {
          ??"e":?"AQAB",
          ??"kty":?"RSA",
          ??"n":?"wVKQLBUqOBiay2dkn9TlbfuaF40_edIKUmdLq6OlvzEMrP4IDzdOk50TMO0nfjJ6v5830_5x0vRg5bzZQeKpHniR0sw7qyoSI6n2eSkSnFt7P-N8gv2KWnwzVs_h9FDdeLOeVOU8k_qzkph3_tmBV7ZZG-4_DEvgvat6ifEC-WzzYqofsIrTiTT7ZFxTqid1q6zrrsmyU2DQH3WdgFiOJVVlN2D0BuZu5X7pGZup_RcWzt_9T6tQsGeU1juSuuUk_9_FVDXNNCTObfKCTKXqjW95ZgAI_xVrMeQC5nXlMh6VEaXfO83oy1j36wUoVUrUnkANhp-dnjTdvJgwN82dGQ"
          }

          其中 kty 字段是必須的,代表密鑰類型,支持 EC 橢圓曲線密鑰,RSA 密鑰和 oct 對稱密鑰。

          JWK 和 公鑰格式 Pem 是可以互相轉(zhuǎn)換的:

          我們現(xiàn)在已經(jīng)知道,驗證這個 JWT 是需要公鑰或 JWK 的,那你會不會好奇 jwt.io 這個網(wǎng)站是怎么知道 JWK 的呢,為什么一粘貼,就自動將 JWK 填充進去了。

          原理其實很簡單,而且已經(jīng)是一種大家都遵循的規(guī)范了,就是將 JWK 放在 iss/.well-known/jwks.json 下,其中 iss 就是 Payload 里面的 iss 。

          當你在 jwt.io 粘貼下 JWT 的瞬間,jwt.io 會先解析 Header ,判斷出 JWT 使用的算法(JWA),接著解析出 Payload 的信息,由于這里是 RS256 算法, 所以還會去請求 Payload 里的 iss 下的 .well-known/jwks.json得到 JWK ,從而完成 JWS 的驗證。

          4)另一種 JWT 的實現(xiàn) :JWE

          我們說過,經(jīng)過 Signature 簽名后的 JWT 就是指的 JWS ,而 JWS 僅僅是對前兩部分簽名,保證無法篡改,但是其 Payload(載荷) 信息是暴露的(只是作了 base64UrlEncode 處理)。因此,使用 JWS 方式的 Payload 是不適合傳遞敏感數(shù)據(jù)的,JWT 的另一種實現(xiàn) JWE 就是來解決這個問題的。

          JWE 全稱是 JSON Web Encryption ( RFC 7516[8] ) ,JWS 的 Payload 是 Base64Url 的明文,而 JWE 的數(shù)據(jù)則是經(jīng)過加密的。它可以使 JWT 更加安全。

          JWE 提供了兩種方案:共享密鑰方案和公鑰/私鑰方案。共享密鑰方案的工作原理是讓各方都知道一個密鑰,大家都可以簽名驗證,這和 JWS 是一致的。而公鑰/私鑰方案的工作方式就不同了,在 JWS 中私鑰對令牌進行簽名,持有公鑰的各方只能驗證這些令牌;但在 JWE 中,持有私鑰的一方是唯一可以解密令牌的一方,公鑰持有者可以引入或交換新數(shù)據(jù)然后重新加密,因此,當使用公鑰/私鑰方案時,JWS 和 JWE 是互補的。

          想要理解這一點的更簡單的方法是從生產(chǎn)者和消費者的角度進行思考。生產(chǎn)者對數(shù)據(jù)進行簽名或加密,消費者可以對其進行驗證或解密。對于 JWS ,私鑰對 JWT 進行簽名,公鑰用于驗證,也就是生產(chǎn)者持有私鑰,消費者持有公鑰,數(shù)據(jù)流動只能從私鑰持有者到公鑰持有者。相比之下,對于 JWE ,公鑰是用于加密數(shù)據(jù),而私鑰用來解密,在這種情況下,數(shù)據(jù)流動只能從公鑰持有者到私鑰持有者。如下圖所示(來源 JWT Handbook[9] ):

          相比于 JWS 的三個部分,JWE 有五個部分組成(四個小數(shù)點隔開)。一個 JWE 示例如下:

          eyJhbGciOiJSU0ExXzUiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0.
          UGhIOguC7IuEvf_NPVaXsGMoLOmwvc1GyqlIKOK1nN94nHPoltGRhWhw7Zx0-kFm1NJn8LE9XShH59_
          i8J0PH5ZZyNfGy2xGdULU7sHNF6Gp2vPLgNZ__deLKxGHZ7PcHALUzoOegEI-8E66jX2E4zyJKxYxzZIItRzC5hlRirb6Y5Cl_p-ko3YvkkysZIFNPccxRU7qve1WYPxqbb2Yw8kZqa2rMWI5ng8Otv
          zlV7elprCbuPhcCdZ6XDP0_F8rkXds2vE4X-ncOIM8hAYHHi29NX0mcKiRaD0-D-ljQTPcFPgwCp6X-nZZd9OHBv-B3oWh2TbqmScqXMR4gp_A.
          AxY8DCtDaGlsbGljb3RoZQ.
          KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.
          9hH0vgRfYgPnAHOd8stkvw
          • Protected Header (受保護的頭部) :類似于 JWS 的 Header ,標識加密算法和類型。
          • Encrypted Key (加密密鑰) :用于加密密文和其他加密數(shù)據(jù)的密鑰。
          • Initialization Vector (初始化向量) :一些加密算法需要額外的(通常是隨機的)數(shù)據(jù)。
          • Encrypted Data (Ciphertext) (加密的數(shù)據(jù)) :被加密的數(shù)據(jù)。
          • Authentication Tag (認證標簽) :算法產(chǎn)生的附加數(shù)據(jù),可用于驗證密文內(nèi)容不被篡改。

          這五個部分的生成,也就是 JWE 的加密過程可以分為 7 個步驟:

          1. 根據(jù) Header alg 的聲明,生成一定大小的隨機數(shù)

          2. 根據(jù)密鑰管理方式確定 Content Encryption Key ( CEK )

          3. 根據(jù)密鑰管理方式確定 JWE Encrypted Key

          4. 計算所選算法所需大小的 Initialization Vector (IV)。如果不需要,可以跳過

          5. 如果 Header 聲明了 zip ,則壓縮明文

          6. 使用 CEK、IV 和 Additional Authenticated Data ( AAD,額外認證數(shù)據(jù) ) ,通過 Header enc 聲明的算法來加密內(nèi)容,結(jié)果為 Ciphertext 和 Authentication Tag

          7. 最后按照以下算法構(gòu)造出 Token:

            base64(header)?+?'.'?+
            base64(encryptedKey)?+?'.'?+?//?Steps?2?and?3
            base64(initializationVector)?+?'.'?+?//?Step?4
            base64(ciphertext)?+?'.'?+?//?Step?6
            base64(authenticationTag)?//?Step?6

          JWE 相比 JWS 更加安全可靠,但是不夠輕量,有點復雜。

          5)安全性考慮

          不管怎樣,JWT 多多少少還是存在一些安全性隱患的,下面是平時開發(fā)過程的一些建議:

          1. 始終執(zhí)行算法驗證

            簽名算法的驗證固定在后端,不以 JWT 里的算法為標準。假設每次驗證 JWT ,驗證算法都靠讀取 Header 里面的 alg 屬性來判斷的話,攻擊者只要簽發(fā)一個 "alg: none" 的 JWT ,就可以繞過驗證了。

          2. 選擇合適的算法

            具體場景選擇合適的算法,例如分布式場景下,建議選擇 RS256 。

          3. HMAC 算法的密鑰安全

            除了需要保證密鑰不被泄露之外,密鑰的強度也應該重視,防止遭到字典攻擊。

          4. 避免敏感信息保存在 JWT 中

            JWS 方式下的 JWT 的 Payload 信息是公開的,不能將敏感信息保存在這里,如有需要,請使用 JWE 。

          5. JWT 的有效時間盡量足夠短

            JWT 過期時間建議設置足夠短,過期后重新使用 refresh_token 刷新獲取新的 token 。

          6)總結(jié)

          今天為大家講了一些 JWT 不為人知的秘密,總結(jié)一下涉及到的知識點:

          • JOSE:規(guī)范網(wǎng)絡傳輸過程中使用 JSON 的一系列標準
          • JWT:以 JSON 編碼并由 JWS 或 JWE 安全傳遞的表示形式
          • JWS:簽名和驗證 Token
          • JWE:加密和解密 Token
          • JWA:定義 JOSE 體系中涉及到的所有算法
          • JWK:用 JSON 來表示密鑰

          最后,再次附上 JOSE 的體系圖,相關(guān)的 RFC 均備注在圖上了:

          希望今天的分享能讓你更加了解 JWT!

          參考資料

          [1]

          RFC 7519: https://datatracker.ietf.org/doc/rfc7519/

          [2]

          jwt.io: https://jwt.io/

          [3]

          RFC 7165: https://www.rfc-editor.org/rfc/rfc7165.html

          [4]

          RFC 7520: https://www.rfc-editor.org/rfc/rfc7520.html

          [5]

          RFC 7518: https://www.rfc-editor.org/rfc/rfc7518.html

          [6]

          RFC 7515: https://www.rfc-editor.org/rfc/rfc7515.html

          [7]

          RFC 7517: https://www.rfc-editor.org/rfc/rfc7517.html

          [8]

          RFC 7516: https://www.rfc-editor.org/rfc/rfc7516.html

          [9]

          JWT Handbook: https://auth0.com/resources/ebooks/jwt-handbook


          1、一天之間,我寫的腳本錯誤干掉了一萬部手機
          2、阿里巴巴建議的線程池創(chuàng)建方式,你用上了嗎?
          3、Redis 作者:每天花6小時搞開源,頂不住了!
          4、DDD到底是何方神圣?今兒聊聊DDD!
          5、上午寫了一段代碼,下午就被開除了,奇怪的知識又增加了!
          6、21 款 yyds 的 IDEA插件
          7、越老越值錢,除了程序員!!

          點分享

          點收藏

          點點贊

          點在看

          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  长腿女神打扫偷懒被主人猛操惩罚 | 高清无码一区二区三区 | 婷婷色一二三区波多野结衣 | 超碰免费人妻 | 豆花视频成人网站入口免费观看 |