jwt 就是這麼簡單

浮x塵發表於2018-08-14

文章不保證最新,最新版請到部落格 www.huborui.com 檢視。

JSON Web Token 是一個非常簡單實用的規範,通過它可以在客戶端和服務端之前傳遞安全可靠的資料。

jwt 由三部分組成:

  • 頭部(header)
  • 載荷(payload)
  • 簽名(signature)

將這三部分用 . 連線起來就構成一個 jwt(header.payload.signature)。

下面就通過這三個部分道出從 jwt 生成到獲取資料的原理。

header

header 描述 jwt 的基本資訊,如型別、簽名所用演算法等。

{
    // 型別為 JWT
    "typ": "JWT",
    // HS256 演算法
    "alg": "HS256"
}
複製程式碼

對 header 進行 Base64 編碼,得到第一部分。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
複製程式碼

沒錯,Base64 編碼並不是加密方式,可以還原的!不加密我們的 jwt 還安全麼?繼續看下去。

payload

payload 是攜帶資料的地方,我們可以將需要傳遞到服務端的資料放在 payload 內。

既然我們的寶貝資料放在 payload,那它會不會被加密?

不會!還是 Base64 編碼,可以還原的!所以不要往裡面放貴重的資料。

{
    // 官方定義了 5 個字標識一些資訊
    // jwt 簽發者
    "iss": "god",
    // 在什麼時候簽發 
    "iat": 1441525213,
    // exp 什麼時候過期 Unix 時間戳
    "exp": 1441525324,
    // 接收 jew 的使用者
    "aud": "xxx@yyy.com"
    // jwt 面向的使用者
    "sub": "xxx@yyy.com"
    // 剩下的就可以自己定義了
    "userID": 12345,
    ...
}
複製程式碼

依舊 Base64 編碼,得到第二部分的字串和 header 用 . 拼在一起。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0
複製程式碼

別急,是不是覺得都是明文的資料,伺服器如何判斷 jwt 的真假呢?下面就到了簽名加密環節。

signature

在簽名環節,我們需要提供一個只有你知道的金鑰(secret),對連在一起的 header 和 payload 用 HS256 演算法加密,得到加密後的字串,和前面的拼在一起:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
複製程式碼

三部分合體成功!jwt 構造成功!

防偽

是否能偽造 jwt 呢?仔細想想就知道,如果你不知道服務端的金鑰,手動修改 header 或 payload 的任何部分,得到的 Base64 編碼就不一樣了,新的編碼經過金鑰生成的簽名肯定和舊的不同。沒有正確的簽名,伺服器會直接返回錯誤。

伺服器驗證一個 jwt 的過程也很簡單:

  1. 收到 jwt
  2. 將 header 和 payload 用金鑰和對應的演算法簽名
  3. 判斷生成的簽名和 jwt 第三部分是否一致
  4. 不一致則返回錯誤,一致則表示 payload 內的資料可信

總結

jwt 的核心就是金鑰,擁有金鑰就擁有生成 jwt 的權利(千萬不能洩露)。

payload 中的資料不是加密的,不要放敏感資料。

參考資料

相關文章