前言:
在現代的Web應用中,安全和高效的用戶身份驗證機制是至關重要的。本文將深入探討基于令牌的用戶登錄會話機制,特別是在使用Redis進行會話管理的情景。通過這一案例實戰,我們將了解令牌如何在用戶身份驗證過程中發揮核心作用,并確保用戶會話的安全性和有效性。
令牌檢查與Redis驗證
用戶平時會訪問我們的系統,在處理任何一個請求之前,必須檢查一下,這個請求是否帶上了一個令牌。如果帶了一個令牌,那么此時就必須在Redis里檢查一下,這個令牌是否有在Redis里合法的、有效的一個session會話。如果有這個session會話,此時就可以允許這個請求被處理,因為說明這個人之前已經登錄過我們的系統了,登錄過后才會在Redis里放一個有效的session會話;如果說沒有這個session的話,此時就會導致用戶必須強制被迫登錄。
用戶登錄與令牌發放
如果用戶登錄通過之后,就會返回給瀏覽器或者客戶端一塊令牌,同時在Redis里初始化好一個session會話。后續客戶端就會在指定時間范圍內發送請求的時候帶上一塊令牌,每次令牌和服務器端的session校驗通過就可以執行請求。
令牌過期與強制登錄
過一段時間過后,服務端的Redis里的session會話就會過期。過期了之后,又會導致你必須要重新登錄,雖然你可能帶上了令牌,但是一檢查發現這塊令牌對應的Redis里的session已經過期了。
Redis命令操作
hset把用戶id和令牌存儲一下,hset把用戶id和過期令牌過期時間存儲一下。每次訪問系統都讓用戶帶上令牌,如果令牌不存在就是沒登錄,hget獲取存儲的令牌和過期時間,如果令牌過期了也要強制登錄,如果令牌校驗通過,這次請求就可以通過。如果令牌要是過期了,就用hdel把存儲的令牌和過期時間都刪了。
代碼:
package com.example.session;import redis.clients.jedis.Jedis;import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.UUID;/*** 示例:用戶會話管理*/
public class UserSessionManager {private Jedis redisClient = new Jedis("127.0.0.1");/*** 驗證會話是否有效* @param sessionToken 會話令牌* @return 有效性*/public boolean checkSessionValidity(String sessionToken) throws Exception {if(sessionToken == null || sessionToken.isEmpty()) {return false;}String sessionData = redisClient.hget("user_sessions", "session_token:" + sessionToken);if(sessionData == null || sessionData.isEmpty()) {return false;}String sessionExpiry = redisClient.hget("session_expiration_times", "session_token:" + sessionToken);if(sessionExpiry == null || sessionExpiry.isEmpty()) {return false;}SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date sessionExpiryDate = dateFormat.parse(sessionExpiry);if(new Date().after(sessionExpiryDate)) {return false;}return true;}/*** 用戶登錄* @param user 用戶名* @param pass 密碼* @return 會話令牌*/public String loginUser(String user, String pass) {System.out.println("登錄用戶:" + user + ", 密碼:" + pass);long userId = new Random().nextInt(100000);String token = UUID.randomUUID().toString().replace("-", "");initializeSession(userId, token);return token;}/*** 初始化用戶會話* @param userId 用戶ID* @param token 會話令牌*/public void initializeSession(long userId, String token) {SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Calendar calendar = Calendar.getInstance();calendar.add(Calendar.HOUR, 24);String sessionExpiry = dateFormat.format(calendar.getTime());redisClient.hset("user_sessions", "session_token:" + token, String.valueOf(userId));redisClient.hset("session_expiration_times", "session_token:" + token, sessionExpiry);}public static void main(String[] args) throws Exception {UserSessionManager sessionManager = new UserSessionManager();boolean isValid = sessionManager.checkSessionValidity(null);System.out.println("初次訪問,會話驗證:" + (isValid ? "通過" : "不通過"));String sessionToken = sessionManager.loginUser("alice","password123");System.out.println("登錄后獲得令牌:" + sessionToken);isValid = sessionManager.checkSessionValidity(sessionToken);System.out.println("再次訪問,會話驗證:" + (isValid ? "通過" : "不通過"));}
}