文章不保證最新,最新版請到部落格 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 的過程也很簡單:
- 收到 jwt
- 將 header 和 payload 用金鑰和對應的演算法簽名
- 判斷生成的簽名和 jwt 第三部分是否一致
- 不一致則返回錯誤,一致則表示 payload 內的資料可信
總結
jwt 的核心就是金鑰,擁有金鑰就擁有生成 jwt 的權利(千萬不能洩露)。
payload 中的資料不是加密的,不要放敏感資料。