1.session
session不是在瀏覽器第一次請求時創建,而是在第一次使用時創建(request.getSession())。
最終創建邏輯在org.apache.catalina.connector.Request的doGetSession()方法中,如下代碼可以看到,這裏會讓請求方設置一個cookie:JSESSIONID
/* org.apache.catalina.connector.Request doGetSession() 部分代碼 */
Cookie cookie = ApplicationSessionCookieConfig.createSessionCookie(context, this.session.getIdInternal(), this.isSecure());
this.response.addSessionCookieInternal(cookie);
注意:服務端使用一個ConcurrentHashMap存儲session,由於session是存儲在應用中的,因此也存在session集羣共享問題,爲解決session共享問題,可使用spring-session。
2.spring-session
spring-session就是把session的存儲從應用中剝離出來單獨存儲,一般存放在緩存如redis中,這樣應用集羣都從redis單機或集羣中獲取session,也就不存在session共享問題了。
使用spring-session的示例
3.token
session的主要作用就是存儲用戶相關數據,token作用與session類似,個人理解爲session的改進版。
token與session對比:
- 客戶端sessionId存儲在瀏覽器的cookie中,token可以存儲在localStorage、cookie、sessionStorage中。
- 服務端session存儲在應用中,token關聯的數據則可以存儲在應用或者緩存中。如果服務端重啓,session失效,token如果在緩存中則仍然有效。
- 如果客戶端禁用cookie,session將失效,客戶端如果將token保存在非cookie中,則仍然有效。
- token的邏輯需要單獨寫。
4.JWT
Json web token (JWT),用於作爲JSON對象在各方之間安全地傳輸信息。JWT由三個部分組成:header(頭部)、payload(載荷)、signature(簽名)。
header
tpy:聲明使用JWT,alg:用於生產簽名的算法
{
'typ': 'JWT',
'alg': 'HS256'
}
通過base64生成header部分:eyd0eXAnOidKV1QnLCdhbGcnOidIUzI1Nid9
payload
載荷一般存儲用戶相關信息,由於只進行base64編碼,因此不建議存儲敏感數據。
以下爲默認提供的字段,除此以外,可以使用自定義的字段如用戶名、暱稱等。
iss:發行人
exp:到期時間
sub:主題
aud:用戶
nbf:在此之前不可用
iat:發佈時間
jti:JWT ID用於標識該JWT
再構建完後同樣需要進行base64編碼生成payload部分。
signature
通過header、payload部分,再使用header中聲明的算法,結合鹽,最後通過base64編碼生成signature部分。
三部分使用 . 相連構成了最終的JWT——header.payload.signature。
缺點分析:
- 由於用戶相關數據從服務端轉移到客戶端JWT中的payload中,並且會隨每次請求攜帶,可以理解爲每次請求都會帶一些無用的數據,因此不建議payload存儲過多的數據。
- 修改payload中的數據時需要重新構造JWT,因此如果payload中的數據修改較爲頻繁,建議使用session或token。
- JWT過期時間不支持動態刷新,並且在有效期間JWT將一直生效,不能取消。
適用場景:
- 一次性驗證:如郵箱激活,好處是服務端不用保存激活相關的數據,都放到JWT的payload中了。
- 接口鑑權:即作爲請求端有權訪問服務端的標識。
有關JWT詳細點的介紹可以觀看https://www.liqingbo.cn/docs/jwt/
——以上僅爲個人見解,如有不正確的地方歡迎指正!