SpringBoot Cookie & Session 用戶登錄及登錄狀態(tài)保持功能實現(xiàn)代碼
會話技術(shù)
- 功能:提供用戶登陸成功后的登陸標記 (一次登錄,一段時間都登錄)
- 會話
- 定義:包含一次或多次請求和響應的訪問操作
- 建立會話:用戶打開瀏覽器訪問 Web 服務器資源時建立會話
- 結(jié)束會話:一方斷開連接時結(jié)束會話
- 會話跟蹤
- 定義:一種維護瀏覽器狀態(tài)的方法
- 功能:服務器通過會話跟蹤來識別多次請求是否來自于同一瀏覽器
- 同一次會話的多次請求間共享數(shù)據(jù)
- 會話跟蹤方案
客戶端會話跟蹤技術(shù) : Cookie

服務端會話跟蹤技術(shù) : Session

令牌技術(shù)(token)
令牌 : 用戶身份的標識,實際上就是一個字符串
Cookie
定義:瀏覽器訪問服務器后,服務器傳給瀏覽器的一段數(shù)據(jù),由瀏覽器保存,后續(xù)通信中瀏覽器也要將 Cookie 發(fā)送給服務器功能- 識別用戶身份 (uid)
- 存儲用戶偏好:讓瀏覽器記住這位訪客的特定信息
工作條件- 瀏覽器每次訪問該服務器,都必須帶上 Cookie
- 瀏覽器需要保存 Cookie,不得輕易刪除
- 不能跨域
工作流程- 客戶端提交一個HTTP請求給服務端
- 服務端 Set-Cookie,同時提交響應內(nèi)容給客戶端
- 客戶端再次向服務器請求,并在請求頭中攜帶一個Cookie
有效期- Expire 值:Cookie 在生成時就會被指定一個 Expire 值,這就是 Cookie 的生存周期
- 立即清除 Cookie:生存周期設(shè)置為 “0” 或負值,這樣在關(guān)閉瀏覽器時,就馬上清除 Cookie,不會記錄用戶信息,更加安全
缺點- 數(shù)量限制:一個瀏覽器能創(chuàng)建的 Cookie 數(shù)量最多為 300 個,并且每個不能超過 4KB,每個 Web 站點能設(shè)置的 Cookie 總數(shù)不能超過 20 個
- 安全性低:存在跨站點腳本攻擊的可能,腳本指令可以讀取當前站點的所有 Cookie 內(nèi)容,并且可以提交到指定服務器重現(xiàn)其功能
問:為什么需要 Cookie 答:web程序使用的HTTP協(xié)議是無狀態(tài)的協(xié)議,對于事務處理沒有記憶能力,如果后續(xù)處理需要前面的信息則必須重傳,導致每次連接傳送的數(shù)據(jù)量增大
Session
一、概述
定義- Session (會話控制),Session 對象存儲特定用戶會話所需的屬性及配置信息
- SessionID:客戶端第一次請求服務器時,服務器為客戶端算出的一個值,存儲在 Cookie 中,用于定位用戶 Session 在服務器中的位置
- 與 Cookie 的區(qū)別:Cookie 可以通過偽造來實現(xiàn)登錄并進行一些 HTTP 請求,從安全性上來講,Session 比 Cookie 安全性稍微高一些
功能:提高安全性有效期:一般為半小時,可以根據(jù)需求設(shè)定缺點:Session 是存儲在服務器當中的,所以 Session 過多,會對服務器產(chǎn)生壓力
二、相關(guān)工具類
HttpSession- 定義:javax.servlet.http.HttpSession 類,是 JavaWeb 自帶的工具類
- 常用方法
- 命令
- 功能
- getAttribute(“attributeName”)
- 獲取指定名稱的屬性值
- setAttribute(“attributeName”, myAttributeObject)
- 設(shè)置指定名稱的屬性值
DTO:Data Transfer Object,在 Session 中的 MyClass 應該去掉敏感信息,轉(zhuǎn)為 MyClassDTO 進行傳輸
三、認證流程
工作流程
- 創(chuàng)建 Session :用戶第一次請求服務器的時候,服務器根據(jù)用戶提交的相關(guān)信息,創(chuàng)建對應的 Session
- 響應 Session ID:服務器響應請求時,將此 Session 的唯一標識信息 SessionID 返回給瀏覽器
- 存入 Cookie:瀏覽器接收到服務器返回的 SessionID 信息后,將此信息存入到 Cookie 中,同時 Cookie 記錄此 SessionID 屬于哪個域名
- 攜帶 Cookie:當用戶第二次訪問服務器的時候,請求會自動判斷此域名下是否存在 Cookie 信息
- 存在 Cookie → 自動將 Cookie 信息也發(fā)送給服務端,服務端會從 Cookie 中獲取 SessionID,再根據(jù) SessionID 查找對應的 Session 信息
- 找到 Session → 證明用戶已經(jīng)登錄可執(zhí)行后面操作
- 未找到 Session → 可能是已過期的 Session 或者是假 Cookie
- 不存在 Cookie → 說明用戶沒有登錄或者登錄失效
- 存在 Cookie → 自動將 Cookie 信息也發(fā)送給服務端,服務端會從 Cookie 中獲取 SessionID,再根據(jù) SessionID 查找對應的 Session 信息
原理說明
- 登錄:客戶端提交登錄表單
- 校驗:服務器進行登錄校驗(如果校驗失敗在直接拋出異常)
- 獲取 Session 對象
- Request 中已經(jīng)有 Session → 獲取 HttpSession 對象
- Request 中還沒有 Session → 創(chuàng)建 HttpSession 對象,并生成唯一標識符(SessionId)
- request.getSession() // 如果 request 中有 session 則獲取
- 更新登錄狀態(tài):將用戶對象 user 以 USER_LOGIN_STATE 為鍵存儲在該 HttpSession 中
- USER_LOGIN_STATE 是一個常量,用來標識用戶登錄狀態(tài)
- request.getSession().setAttribute(USER_LOGIN_STATE, user); // 更新Session登錄狀態(tài)
- 設(shè)置過期時間:設(shè)置該 HttpSession 的過期時間為 1 小時(即 1 小時如果內(nèi)沒有與該 HttpSession 關(guān)聯(lián)的請求,該 HttpSession 將被自動銷毀)
request.getSession().setMaxInactiveInterval(60 * 60); // 設(shè)定Session過期時間
- 回傳 SessionId:服務器將 SessionId 寫入 Response Headers 中的 Set-Cookie
HTTP/1.1 200 OK Set-Cookie: JSESSIONID=1234567890ABCDEF; Path=/; HttpOnly
- 保存 SessionId:客戶端將 SessionId 存儲在 Cookie 中
- 客戶端請求資源:客戶端登錄后,每次訪問服務器都會將 SessionId 寫在 請求頭的 Cookie 屬性中
GET /some/resource HTTP/1.1 Host: www.example.com Cookie: JSESSIONID=1234567890ABCDEF
四、示例
實現(xiàn)邏輯
創(chuàng)建 DTO 類- 創(chuàng)建 com.projectname.dto.UserDTO 類
- 定義 UserDTO 類中的屬性 (希望展示的 User 的屬性)
創(chuàng)建 UserHolder 工具類- 創(chuàng)建 com.projectname.utils.UserHolder 類
- 定義 ThreadLocal 本地線程 tl
- 定義 save / get / remove 方法
修改 UserServiceImpl 中的返回值- 調(diào)用 hutools 的 BeanUtil 工具類,使用其 copyProperties(User, UserDTO.class) 方法進行 DTO 映射
- 修改 session 中的返回值 (User → UserDTO)
- session.setAttribute(”User”, BeanUtil.copyProperties( user, UserDTO.class)
修改 UserController 中的返回值- UserDTO user = UserHolder.getUser();
- 創(chuàng)建攔截器
- 獲取用戶請求的 Token 或其他標識
- 驗證 Token,并解析出用戶信息
- 將用戶信息存入
UserHolder - 在請求完成后清除
UserHolder的數(shù)據(jù),防止內(nèi)存泄漏
- 配置攔截器:注冊攔截器,讓其攔截需要驗證的路徑
示例代碼
UserDTO 類(com.projectname.dto.UserDTO)
// com.projectname.dto.UserDTO
@Data
public class UserDTO {
private Long id;
private String nickName;
private String icon;
}
UserHolder 類(com.myproject.utils.UserHolder.java)
// com.projectname.utils.UserHolder
public class UserHolder {
private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();
public static void saveUser(UserDTO user){
tl.set(user);
}
public static UserDTO getUser(){
return tl.get();
}
public static void removeUser(){
tl.remove();
}
}- 攔截器(com.myproject.config.UserInterceptor.java)
- 目標:自動攔截所有請求,如果有用戶信息則存入 UserHolder 中
@Component
public class UserInterceptor implements HandlerInterceptor {@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 從請求頭中獲取 Token,如果沒有 Token 則跳過攔截器(可能是未登錄狀態(tài))
String token = request.getHeader("Authorization");
if (!StringUtils.hasText(token)) {
return true;
}
// 2. 校驗 Token 并解析用戶信息(此處簡單模擬,實際應調(diào)用 Token 驗證服務或工具類)
UserDTO user = validateTokenAndGetUser(token);
if (user == null) { // 如果解析失敗,允許繼續(xù)(未登錄狀態(tài))
return true;
}
// 3. 將用戶信息保存到 UserHolder 中
UserHolder.setUser(user);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 請求處理完成后清理 ThreadLocal,防止內(nèi)存泄漏
UserHolder.clear();
}
// 模擬 Token 校驗并獲取用戶信息
private UserDTO validateTokenAndGetUser(String token) {
// 示例:模擬解析 Token 獲取用戶
if ("valid-token".equals(token)) {
return getUserByToken(token);
}
return null; // Token 無效或解析失敗
}}
- 配置攔截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserInterceptor userInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userInterceptor) // 注冊攔截器
.addPathPatterns("/**") // 攔截所有路徑
.excludePathPatterns("/login", "/register"); // 排除登錄、注冊等公開路徑
}
}到此這篇關(guān)于SpringBoot Cookie & Session 用戶登錄及登錄狀態(tài)保持功能實現(xiàn)代碼的文章就介紹到這了,更多相關(guān)springboot cookie session用戶登錄內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java數(shù)據(jù)結(jié)構(gòu)排序算法之歸并排序詳解
這篇文章主要介紹了java數(shù)據(jù)結(jié)構(gòu)排序算法之歸并排序,結(jié)合具體實例形式詳細分析了歸并排序的原理、實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下2017-05-05
Mybatis-plus如何在xml中傳入自定義的SQL語句
這篇文章主要介紹了Mybatis-plus如何在xml中傳入自定義的SQL語句問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
Java中的synchronized關(guān)鍵字全解析
synchronized是Java中用于解決并發(fā)問題的核心關(guān)鍵字,通過確保多個線程對共享資源的互斥訪問,來避免線程安全問題,synchronized具有原子性、可見性、有序性和可重入性等特性,本文給大家介紹Java中的synchronized關(guān)鍵字相關(guān),感興趣的朋友跟隨小編一起看看吧2026-01-01
Spring Boot 2.X整合Spring-cache(讓你的網(wǎng)站速度飛起來)
這篇文章主要介紹了Spring Boot 2.X整合Spring-cache(讓你的網(wǎng)站速度飛起來),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-09-09

