基于Redis實現(xiàn)雙加密Token的示例代碼
1. 核心設計思路
TokenStore類的核心設計目標是實現(xiàn)一個高效、安全的Token管理系統(tǒng),主要功能包括:
- Token的生成與存儲:用戶登錄時生成
accessToken和refreshToken,并將其存儲在Redis中。 - Token的刷新:通過
refreshToken獲取新的accessToken。 - Token的刪除:刪除用戶的所有Token,通常用于用戶注銷或管理員禁用用戶。
- 用戶信息的獲取:通過
accessToken獲取用戶的詳細信息。
為了實現(xiàn)這些功能,TokenStore類依賴Redis作為存儲介質(zhì),利用Redis的高性能和豐富的數(shù)據(jù)結構(如String、Set)來管理Token和用戶信息。
2. 關鍵代碼邏輯分析
2.1 Token的生成與存儲
在用戶登錄時,系統(tǒng)會生成一個accessToken和一個refreshToken,并將它們存儲在Redis中。以下是storeAccessToken方法的核心邏輯:
public TokenInfoBO storeAccessToken(UserInfoInTokenBO userInfoInToken) {
TokenInfoBO tokenInfoBO = new TokenInfoBO();
String accessToken = IdUtil.simpleUUID(); // 生成隨機的accessToken
String refreshToken = IdUtil.simpleUUID(); // 生成隨機的refreshToken
tokenInfoBO.setUserInfoInToken(userInfoInToken);
tokenInfoBO.setExpiresIn(getExpiresIn(userInfoInToken.getSysType())); // 設置Token過期時間
String uidToAccessKeyStr = getUidToAccessKey(getApprovalKey(userInfoInToken)); // 生成uid_to_access的Redis Key
String accessKeyStr = getAccessKey(accessToken); // 生成access_token的Redis Key
String refreshToAccessKeyStr = getRefreshToAccessKey(refreshToken); // 生成refresh_to_access的Redis Key
// 將新的Token加入現(xiàn)有Token列表
List<String> existsAccessTokens = new ArrayList<>();
existsAccessTokens.add(accessToken + StrUtil.COLON + refreshToken);
// 檢查并清理過期的Token
Long size = redisTemplate.opsForSet().size(uidToAccessKeyStr);
if (size != null && size != 0) {
List<String> tokenInfoBoList = stringRedisTemplate.opsForSet().pop(uidToAccessKeyStr, size);
if (tokenInfoBoList != null) {
for (String accessTokenWithRefreshToken : tokenInfoBoList) {
String[] accessTokenWithRefreshTokenArr = accessTokenWithRefreshToken.split(StrUtil.COLON);
String accessTokenData = accessTokenWithRefreshTokenArr[0];
if (BooleanUtil.isTrue(stringRedisTemplate.hasKey(getAccessKey(accessTokenData)))) {
existsAccessTokens.add(accessTokenWithRefreshToken);
}
}
}
}
// 使用Redis管道批量操作
redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
long expiresIn = tokenInfoBO.getExpiresIn();
byte[] uidKey = uidToAccessKeyStr.getBytes(StandardCharsets.UTF_8);
byte[] refreshKey = refreshToAccessKeyStr.getBytes(StandardCharsets.UTF_8);
byte[] accessKey = accessKeyStr.getBytes(StandardCharsets.UTF_8);
// 將Token列表存入Redis
for (String existsAccessToken : existsAccessTokens) {
connection.sAdd(uidKey, existsAccessToken.getBytes(StandardCharsets.UTF_8));
}
// 設置uid_to_access的過期時間
connection.expire(uidKey, expiresIn);
// 存儲refresh_to_access的映射
connection.setEx(refreshKey, expiresIn, accessToken.getBytes(StandardCharsets.UTF_8));
// 存儲access_token對應的用戶信息
connection.setEx(accessKey, expiresIn, Objects.requireNonNull(redisSerializer.serialize(userInfoInToken)));
return null;
});
// 返回加密后的Token
tokenInfoBO.setAccessToken(encryptToken(accessToken, userInfoInToken.getSysType()));
tokenInfoBO.setRefreshToken(encryptToken(refreshToken, userInfoInToken.getSysType()));
return tokenInfoBO;
}
關鍵點分析:
- Token生成:使用
IdUtil.simpleUUID()生成隨機的accessToken和refreshToken,確保Token的唯一性。 - Redis數(shù)據(jù)結構:
uid_to_access:使用Set數(shù)據(jù)結構存儲用戶的所有Token,方便管理和清理。refresh_to_access:使用String數(shù)據(jù)結構存儲refreshToken到accessToken的映射。access_token:使用String數(shù)據(jù)結構存儲accessToken對應的用戶信息。
- 過期時間管理:根據(jù)用戶類型(
sysType)設置不同的Token過期時間,普通用戶和管理員的Token過期時間不同。 - Redis管道操作:通過
executePipelined方法批量執(zhí)行Redis操作,減少網(wǎng)絡開銷,提升性能。
2.2 Token的刷新
當accessToken過期時,用戶可以通過refreshToken獲取新的accessToken。以下是refreshToken方法的核心邏輯:
public ServerResponseEntity<TokenInfoBO> refreshToken(String refreshToken) {
if (StrUtil.isBlank(refreshToken)) {
return ServerResponseEntity.showFailMsg("refreshToken is blank");
}
ServerResponseEntity<String> decryptTokenEntity = decryptToken(refreshToken); // 解密refreshToken
if (!decryptTokenEntity.isSuccess()) {
return ServerResponseEntity.transform(decryptTokenEntity);
}
String realRefreshToken = decryptTokenEntity.getData();
String accessToken = stringRedisTemplate.opsForValue().get(getRefreshToAccessKey(realRefreshToken)); // 獲取對應的accessToken
if (StrUtil.isBlank(accessToken)) {
return ServerResponseEntity.showFailMsg("refreshToken 已過期");
}
ServerResponseEntity<UserInfoInTokenBO> userInfoByAccessTokenEntity = getUserInfoByAccessToken(accessToken, false);
if (!userInfoByAccessTokenEntity.isSuccess()) {
return ServerResponseEntity.showFailMsg("refreshToken 已過期");
}
UserInfoInTokenBO userInfoInTokenBO = userInfoByAccessTokenEntity.getData();
// 刪除舊的refresh_token和access_token
stringRedisTemplate.delete(getRefreshToAccessKey(realRefreshToken));
stringRedisTemplate.delete(getAccessKey(accessToken));
// 生成新的Token
TokenInfoBO tokenInfoBO = storeAccessToken(userInfoInTokenBO);
return ServerResponseEntity.success(tokenInfoBO);
}
關鍵點分析:
- Token解密:通過
decryptToken方法解密refreshToken,確保Token的安全性。 - Token映射:通過
refresh_to_access的映射關系,找到對應的accessToken。 - Token清理:刪除舊的
refreshToken和accessToken,防止Token被重復使用。 - 新Token生成:調(diào)用
storeAccessToken方法生成新的Token。
2.3 Token的刪除
在某些情況下(如用戶注銷或管理員禁用用戶),需要刪除用戶的所有Token。以下是deleteAllToken方法的核心邏輯:
public void deleteAllToken(String appId, Long uid) {
String uidKey = getUidToAccessKey(getApprovalKey(appId, uid)); // 生成uid_to_access的Redis Key
Long size = redisTemplate.opsForSet().size(uidKey);
if (size == null || size == 0) {
return;
}
List<String> tokenInfoBoList = stringRedisTemplate.opsForSet().pop(uidKey, size);
if (CollUtil.isEmpty(tokenInfoBoList)) {
return;
}
// 遍歷并刪除所有Token
for (String accessTokenWithRefreshToken : tokenInfoBoList) {
String[] accessTokenWithRefreshTokenArr = accessTokenWithRefreshToken.split(StrUtil.COLON);
String accessToken = accessTokenWithRefreshTokenArr[0];
String refreshToken = accessTokenWithRefreshTokenArr[1];
redisTemplate.delete(getRefreshToAccessKey(refreshToken));
redisTemplate.delete(getAccessKey(accessToken));
}
redisTemplate.delete(uidKey); // 刪除uid_to_access的Key
}
關鍵點分析:
- 批量刪除:通過
uid_to_access的Set數(shù)據(jù)結構,獲取用戶的所有Token并批量刪除。 - 清理映射關系:刪除
refresh_to_access和access_token的映射關系,確保Token完全失效。
3. 總結
通過對TokenStore類的深入分析,我們可以看到其設計思路清晰,代碼邏輯嚴謹。通過Redis的高效存儲和豐富的數(shù)據(jù)結構,實現(xiàn)了Token的生成、刷新、刪除以及用戶信息的獲取。這種設計不僅保證了系統(tǒng)的安全性,還提升了系統(tǒng)的性能和可擴展性。
希望本文的源碼分析能夠幫助你更好地理解Token管理的實現(xiàn)原理。
到此這篇關于基于Redis實現(xiàn)雙加密Token的示例代碼的文章就介紹到這了,更多相關Redis雙加密Token內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Redis實現(xiàn)布隆過濾器緩存去重的"智能門衛(wèi)"(實例詳解)
布隆過濾器(Bloom Filter)本質(zhì)是一個基于哈希函數(shù)的概率型數(shù)據(jù)結構,核心作用是快速判斷一個元素是否存在于集合中,今天給大家介紹Redis實現(xiàn)布隆過濾器緩存去重的"智能門衛(wèi)",感興趣的朋友跟隨小編一起看看吧2026-02-02
Redis集群刪除后重建后報錯:unrecoverable erro:corrupted clust
這篇文章主要介紹了Redis集群刪除后重建后報錯:unrecoverable erro:corrupted cluster config file問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2026-06-06

