我是陳皮,一個在互聯網 Coding 的 ITer,微信搜索「陳皮的JavaLib」第一時間閱讀最新文章,回復【資料】,即可獲得我精心整理的技術資料,電子書籍,一線大廠面試資料和優秀簡歷模板,
前言
我們知道,HTTP 是無狀態的協議,服務端并不知道哪個請求是哪個用戶發起的,有些場景我們需要知道請求是哪個用戶發起的,哪個用戶操作的,例如商城服務,用戶發起請求下單,服務端需要識別是哪個具體的用戶,所以服務端需要使用某種機制來識別,記錄用戶的資訊,狀態等,
Session 機制就能實作,它可以讓無狀態協議的 HTTP 有狀態化,服務端為每個請求服務端的用戶創建其獨享的 Session,用于標識,跟蹤此用戶,Session 是存盤在服務端的,可以存盤在檔案,記憶體,資料等等,并且有唯一的標識 Session ID,服務端創建 Session 之后,服務端通過 HTTP 協議告訴客戶端,在本地 Cookie 中記錄這個 Session ID,這樣同個客戶端以后的每一個請求將 Cookie 一起發送給服務端,服務端通過存盤在 Cookie 的 Session ID 查出存盤在服務端的 Session ,就能知道此次請求的是哪個用戶了,

Session
Session 中文意思即會話,時效,其實就是客戶端和服務端一對一互動的會話狀態,是一種抽象概念,很多人認為 Session 就是以下代碼獲取的 Session 物件,其實這只是其中的借助 Cookie 的一種通用性較好的實作而已,Session 有很多種實作的,
HttpSession session = request.getSession();
因為大部分應用程式借助 Cookie 來實作 Session 跟蹤,即上述那一行代碼,Cookie 是實際存在的,客戶端請求服務端并且第一次創建 Session 的時候,服務端通過 HTTP 協議(HTTP回應頭的 Set-Cookie)告訴客戶端,需要在本地 Cookie 中記錄這個 Session ID,key 的值為 JSESSIONID,

這樣同個客戶端以后的每一個請求會將 Cookie 一起發送給服務端,服務端通過存盤在 Cookie 的 Session ID 查出存盤在服務端的 Session ,就能知道此次請求的是哪個用戶了,
HttpSession session = request.getSession();
不過客戶端瀏覽器是可以禁用 Cookie 的,那這種方式就會出現問題,但是我們可以使用 URL 重寫的技術來實作 Session 跟蹤,即在請求服務端的所有請求引數增加一個代表用戶標識或者 Session ID 即可,
http://chenpi.com/list?sid=xxx
前面我們說過 Session 可以存盤在檔案,記憶體,資料庫等地方,會話資訊具體存盤在哪里其實都得根據自身業務來定,一切脫離業務場景談技術架構的都是耍流氓, 技術本身無好壞,不過是什么業務場景適合什么技術而已,這也是架構師考慮技術選型的一方面能力,
不過 Session 機制在集群服務中需要考慮 Session 一致性問題,可以在集群服務中做 Session 同步,不過這種方法有一些缺點,例如同步麻煩,同步延遲,多機存盤相同的 Session 浪費存盤空間,另外一種比較常用的方法就是使用專門的 Session 服務集群來保存用戶會話資訊,例如 Redis 快取服務,不僅可搭建集群模式實作高可用可拓展,而且基于記憶體性能速度快,
public UserContext getUserContext(HttpServletRequest request) {
String userToken = getUserToken(request, COOKIE_KEY);
if (!StringUtils.isEmpty(userToken)) {
String userContextStr = redisUtils.getString(RedisKeyUtil.genKey(userToken));
if (!StringUtils.isEmpty(userContextStr)) {
return JSON.parseObject(userContextStr, UserContext.class);
}
}
return null;
}
public String getUserToken(HttpServletRequest request, String cookieName) {
Cookie[] cookies = request.getCookies();
if (null != cookies) {
for (Cookie cookie : cookies) {
if (Objects.equals(cookie.getName(), cookieName)) {
return cookie.getValue();
}
}
}
return null;
}
Cookie
Cookie 是客戶端技術,也是很多人實作 Session 會話的選型,服務端可以讓客戶端將一些資訊寫入本地 Cookie 中,來達到會話跟蹤的目的,不過要注意瀏覽器本地禁用 Cookie 的情況,
說到 Cookie,就不得不說很多廣告商,網站等采用我們個人隱私進行跟蹤,分析我們的行為,進行個性化推薦,很多網站利用第三方 Cookie 獲取用戶資訊,發送到服務端記錄用戶的行為軌跡,你肯定也遇到在其他應用討論到防脫發,然后你打開淘寶驚奇的發現給你推薦各種防脫發洗發液,不過,目前有些瀏覽器已經禁用第三方 Cookie 或者進行優化處理了,例如 Safari,Mozilla 等,
我們可以手動將一些資訊設定到 Cookie 中,這樣客戶端不僅可以使用到這些資訊,在后續的請求中,服務端也能根據此資訊做相應的處理,
public void saveUserContext(HttpServletResponse response, String key, String value) {
// 設定cookie
Cookie cookie = new Cookie(key, value);
cookie.setPath("/");
// 設定有限期,負數例如-1代表Web瀏覽器關閉的時候洗掉,如果不設定就默認-1
cookie.setMaxAge(12 * 60 * 60);
response.addCookie(cookie);
}
我們可以通過瀏覽器查看存盤在本地的 Cookie 資訊,而且其他網站也可以掃描使用我們存盤的 Cookie,所以一些安全性或者保密的資訊盡量不要存盤在 Cookie 中,因為資料安全性比較低,正常情況下,用戶登錄資訊等比較重要資訊存盤在服務端 Session 中,其他資訊例如會話 ID 可以存盤在 Cookie 中,
而且單個 Cookie 的大小也是有限制的,不同瀏覽器限制規則不一樣,一般大小是幾 Kb, 不同瀏覽器對于一個域名下的 Cookie 數量也是有限制的,一般就幾十個,而且也有數量飽和時淘汰策略,所以使用要注意這些情況,盡量不要超過瀏覽器的限制,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/289353.html
標籤:其他
