通常狀況下,客戶的會話數據會存在文件中,或者引入redis來存儲,實現session的管理,可是這樣操做會存在一些問題,使用文件來存儲的時候,在多臺機器上,比較難實現共享,使用redis來存儲的時候,則須要引入多一個集羣,這樣會增長管理的工做量,也不方便。有一個直觀的辦法,就是將session數據,存儲在客戶端中,使用簽名校驗數據是否有篡改,客戶請求的時候,把session數據帶上,獲取裏面的數據,經過校驗,而後進行身份認證。html
數據存儲在客戶端中,會存在一些挑戰:web
爲了實現客戶端存儲會話數據的解決方案,制定了JSON Web Token的協議,詳細的協議能夠在:RFC7529查看。下面咱們看看jwt協議是怎樣解決上面的挑戰的。redis
JWT加密後,使用的格式,分爲三部分,header,payload和signature,使用.號鏈接起來:算法
Header.Payload.Signature
JWT的header,定義了存儲的算法和協議名稱:json
{ "alg": "HS256", "typ": "JWT" }
下面這些負載字段,是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" }
服務端,有一個祕鑰,經過祕鑰對header和payload進行簽名,使用header中指定的簽名算法類型,通常有HMAC,RSA和ECDSA,下面是簽名的格式:session
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
JWT通常會將token數據存儲在http請求的header中,經過Bearer來分隔:數據結構
headers: { 'Authorization': 'Bearer ' + token }
定義好數據結構和通信方式,下面看看如何處理一些問題:加密
每個token產生,都應該限制好過時時間,確保只能在一段時間內有效,保證安全。當達到過時時間時,須要對token進行續簽,能夠定時想服務器提交請求,從新獲取token來實現。
當客戶登陸的時候,須要註銷登陸會話,因爲token是沒有狀態的,只能在客戶端把token刪除,僞造一個註銷的狀態,真正的註銷只能等待token過時。
也能夠有種辦法,就是把token的信息記錄在redis中,當客戶退出時,講redis中的token刪除,而通常請求時,會經過redis對數據進行校驗,這樣能夠實現真的註銷效果,但要引入多一個組件,把token變爲有狀態,若是用這種辦法,也就不符合token存儲在客戶端的模式了
若是可以支持,會話用的數據量較小,對註銷能夠等待超時的長效的場景,使用jwt做爲會話數據存儲是會比較方便的。而對於會話數據量大的場景,仍是使用通常的方式比較好點。