JSON WEB TOKEN(JWT)的分析 一般情況下,客戶的會話數據會存在文件中,或者引入redis來存儲,實現session的管理,但是這樣操作會存在一些問題,使用文件來存儲的時候,在多台機器上,比較難實現共用,使用redis來存儲的時候,則需要引入多一個集群,這樣會增加管理的工作量,也不方便 ...
JSON WEB TOKEN(JWT)的分析
一般情況下,客戶的會話數據會存在文件中,或者引入redis來存儲,實現session的管理,但是這樣操作會存在一些問題,使用文件來存儲的時候,在多台機器上,比較難實現共用,使用redis來存儲的時候,則需要引入多一個集群,這樣會增加管理的工作量,也不方便。有一個直觀的辦法,就是將session數據,存儲在客戶端中,使用簽名校驗數據是否有篡改,客戶請求的時候,把session數據帶上,獲取裡面的數據,通過校驗,然後進行身份認證。
數據存儲在客戶端中,會存在一些挑戰:
- 數據安全問題
- 數據量不能太大
- 續簽的問題
- 註銷的問題
為了實現客戶端存儲會話數據的解決方案,制定了JSON Web Token的協議,詳細的協議可以在:RFC7529查看。下麵我們看看jwt協議是怎樣解決上面的挑戰的。
JWT的結構:
JWT加密後,使用的格式,分為三部分,header,payload和signature,使用.號連接起來:
Header.Payload.Signature
JWT的header:
JWT的header,定義了存儲的演算法和協議名稱:
{
"alg": "HS256",
"typ": "JWT"
}
JWT的Payload:
下麵這些負載欄位,是JWT協議提供選用,一般情況下,payload的數據是不加密存儲在客戶端中的,所以要註意不要存儲敏感信息:
iss (issuer):簽發人
exp (expiration time):過期時間
sub (subject):主題
aud (audience):受眾
nbf (Not Before):生效時間
iat (Issued At):簽發時間
jti (JWT ID):編號
payload除了這些欄位,還可以擴展一些數據,更加符合我們的需求:
{
"iss": "foo",
"extend_data": "hell"
}
JWT的Signature
服務端,有一個秘鑰,通過秘鑰對header和payload進行簽名,使用header中指定的簽名演算法類型,一般有HMAC,RSA和ECDSA,下麵是簽名的格式:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT的通訊方式
JWT一般會將token數據存儲在http請求的header中,通過Bearer來分隔:
headers: {
'Authorization': 'Bearer ' + token
}
定義好數據結構和通訊方式,下麵看看如何處理一些問題:
續簽問題
每一個token產生,都應該限制好過期時間,確保只能在一段時間內有效,保證安全。當達到過期時間時,需要對token進行續簽,可以定時想伺服器提交請求,重新獲取token來實現。
註銷問題
當客戶登錄的時候,需要註銷登錄會話,由於token是沒有狀態的,只能在客戶端把token刪除,偽造一個註銷的狀態,真正的註銷只能等待token過期。
也可以有種辦法,就是把token的信息記錄在redis中,當客戶退出時,講redis中的token刪除,而一般請求時,會通過redis對數據進行校驗,這樣可以實現真的註銷效果,但要引入多一個組件,把token變為有狀態,如果用這種辦法,也就不符合token存儲在客戶端的模式了
總結
如果能夠支持,會話用的數據量較小,對註銷可以等待超時的長效的場景,使用jwt作為會話數據存儲是會比較方便的。而對於會話數據量大的場景,還是使用一般的方式比較好點。