1. Core design ideas
TokenStore
The core design goal of the class is to achieve an efficient and secure Token management system, with its main functions including:
-
Generation and storage of tokens: Generated when the user logs in
accessToken
andrefreshToken
and store it in Redis. -
Token refresh:pass
refreshToken
Get newaccessToken
。 - Token's deletion: Delete all tokens of users, which are usually used to log out of users or to disable users by administrators.
-
Obtaining user information:pass
accessToken
Get user details.
To achieve these functions,TokenStore
Classes rely on Redis as storage medium, leveraging Redis's high performance and rich data structures (e.g.String
、Set
) to manage token and user information.
2. Key code logic analysis
2.1 Token generation and storage
When the user logs in, the system generates aaccessToken
And onerefreshToken
and store them in Redis. The following isstoreAccessToken
The core logic of the method:
public TokenInfoBO storeAccessToken(UserInfoInTokenBO userInfoInToken) { TokenInfoBO tokenInfoBO = new TokenInfoBO(); String accessToken = (); // Generate random accessTokens String refreshToken = (); // Generate random refreshTokens (userInfoInToken); (getExpiresIn(())); // Set the token expiration time String uidToAccessKeyStr = getUidToAccessKey(getApprovalKey(userInfoInToken)); // Generate Redis Key of uid_to_access String accessKeyStr = getAccessKey(accessToken); // Generate Redis Key to access_token String refreshToAccessKeyStr = getRefreshToAccessKey(refreshToken); // Generate Redis Key to refresh_to_access // Add new tokens to existing token list List<String> existsAccessTokens = new ArrayList<>(); (accessToken + + refreshToken); // Check and clean out expired Tokens Long size = ().size(uidToAccessKeyStr); if (size != null && size != 0) { List<String> tokenInfoBoList = ().pop(uidToAccessKeyStr, size); if (tokenInfoBoList != null) { for (String accessTokenWithRefreshToken : tokenInfoBoList) { String[] accessTokenWithRefreshTokenArr = (); String accessTokenData = accessTokenWithRefreshTokenArr[0]; if (((getAccessKey(accessTokenData)))) { (accessTokenWithRefreshToken); } } } } // Batch operation using Redis pipeline ((RedisCallback<Object>) connection -> { long expiresIn = (); byte[] uidKey = (StandardCharsets.UTF_8); byte[] refreshKey = (StandardCharsets.UTF_8); byte[] accessKey = (StandardCharsets.UTF_8); // Save the token list into Redis for (String existsAccessToken : existsAccessTokens) { (uidKey, (StandardCharsets.UTF_8)); } // Set the expiration time of uid_to_access (uidKey, expiresIn); // Storing the mapping of refresh_to_access (refreshKey, expiresIn, (StandardCharsets.UTF_8)); //Storing user information corresponding to access_token (accessKey, expiresIn, ((userInfoInToken))); return null; }); // Return to the encrypted token (encryptToken(accessToken, ())); (encryptToken(refreshToken, ())); return tokenInfoBO; }
Key points analysis:
-
Token generation:use
()
Generate randomaccessToken
andrefreshToken
, ensure the uniqueness of the token. -
Redis data structure:
-
uid_to_access
:useSet
The data structure stores all the user's tokens for easy management and cleaning. -
refresh_to_access
:useString
Data structure storagerefreshToken
arriveaccessToken
map of . -
access_token
:useString
Data structure storageaccessToken
Corresponding user information.
-
-
Expiration time management: According to user type (
sysType
) Set different token expiration times, and the token expiration times of ordinary users and administrators are different. -
Redis Pipeline Operation:pass
executePipelined
Methods batch-execute Redis operations to reduce network overhead and improve performance.
2.2 Token refresh
whenaccessToken
When expired, users can passrefreshToken
Get newaccessToken
. The following isrefreshToken
The core logic of the method:
public ServerResponseEntity<TokenInfoBO> refreshToken(String refreshToken) { if ((refreshToken)) { return ("refreshToken is blank"); } ServerResponseEntity<String> decryptTokenEntity = decryptToken(refreshToken); // Decrypt refreshToken if (!()) { return (decryptTokenEntity); } String realRefreshToken = (); String accessToken = ().get(getRefreshToAccessKey(realRefreshToken)); // Get the corresponding accessToken if ((accessToken)) { return ("refreshToken expired"); } ServerResponseEntity<UserInfoInTokenBO> userInfoByAccessTokenEntity = getUserInfoByAccessToken(accessToken, false); if (!()) { return ("refreshToken expired"); } UserInfoInTokenBO userInfoInTokenBO = (); // Delete old refresh_token and access_token (getRefreshToAccessKey(realRefreshToken)); (getAccessKey(accessToken)); // Generate a new token TokenInfoBO tokenInfoBO = storeAccessToken(userInfoInTokenBO); return (tokenInfoBO); }
Key points analysis:
-
Token decryption:pass
decryptToken
Method decryptionrefreshToken
, ensure the security of the token. -
Token mapping:pass
refresh_to_access
Find the corresponding mapping relationshipaccessToken
。 -
Token cleaning: Delete the old one
refreshToken
andaccessToken
, prevent tokens from being reused. -
New Token Generation: Called
storeAccessToken
Method generates a new token.
2.3 Deletion of Token
In some cases (such as user logout or administrator disable user), all tokens of users need to be deleted. The following isdeleteAllToken
The core logic of the method:
public void deleteAllToken(String appId, Long uid) { String uidKey = getUidToAccessKey(getApprovalKey(appId, uid)); // Generate Redis Key of uid_to_access Long size = ().size(uidKey); if (size == null || size == 0) { return; } List<String> tokenInfoBoList = ().pop(uidKey, size); if ((tokenInfoBoList)) { return; } // traverse and delete all tokens for (String accessTokenWithRefreshToken : tokenInfoBoList) { String[] accessTokenWithRefreshTokenArr = (); String accessToken = accessTokenWithRefreshTokenArr[0]; String refreshToken = accessTokenWithRefreshTokenArr[1]; (getRefreshToAccessKey(refreshToken)); (getAccessKey(accessToken)); } (uidKey); // Delete the Key of uid_to_access}
Key points analysis:
-
Batch Delete:pass
uid_to_access
ofSet
Data structure, obtain all the tokens of the user and delete them in batches. -
Clean up mapping relationships:delete
refresh_to_access
andaccess_token
The mapping relationship ensures that the token is completely invalid.
3. Summary
ByTokenStore
Through in-depth analysis of the class, we can see that its design ideas are clear and the code logic is rigorous. Through Redis' efficient storage and rich data structure, the generation, refresh, deletion and acquisition of user information are realized. This design not only ensures the security of the system, but also improves the performance and scalability of the system.
I hope that the source code analysis of this article can help you better understand the implementation principles of Token management.
This is the end of this article about the example code of implementing dual encryption tokens based on Redis. For more related Redis dual encryption token content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!