Under Microservices, how to realize simultaneous login or forced offline of multiple devices?
Preface:Have you ever encountered a requirement where the product requires the same user to be allowed to log in at the same time according to backend Settings, or when it is not allowed to log in at the same time, it is necessary to force the previous offline scenario. This article will lead you to implement a simple requirement for this scenario
Preface:Have you ever encountered a requirement where the product requires the same user to be allowed to log in at the same time according to backend Settings, or when it is not allowed to log in at the same time, it is necessary to force the previous offline scenario. This article will lead you to implement a simple requirement for this scenario.
Let's take a look at a simple time sequence diagram for future understanding.
Firstly, we need a backend Setting switch to control whether users are allowed to log in to multiple devices simultaneously assuming it is allowed). Secondly, after logging in, we need to save the user's userId token relationship cache. Looking back at the sequence diagram above, can you already understand the principle of implementation.
If your architecture is Microservices, you can use Redis to store the login relationship cache, and the single architecture can directly store the session. This article uses the Microservices architecture, so it uses Redis.
The premises of this article are all based on the same user, and will not be further elaborated in the following text.
1. Construct login cache relationship
If you want to log in to multiple devices of the same user at the same time, you must find each login status of the user in the session Microservices can use Redis for session sharing). If you simply cache the user information, you must have a unique value token when you log in. In this way, each login token is dIfferent, but the tarGet user is the same.
The prefix maintained in the usertoken is user ID, and there is no need to maintain multiple because the hash data type of reids is used. When multiple logins are used, a New row can be added; In the user section, multiple records are maintained here, that is, there is one record after logging in once; Because according to business needs, other user information needs to be obtained from the cache in the future.
- Allow multiple devices to log in simultaneously: there may only be one usertoken, but there may be multiple usertokens
- Do not allow multiple devices to log in at the same time force offline If available): only 1 usertoken and 1 user
/***Cache user information after successful login * * @ paramreq * @ Return*/ Public Void CacheUserInfoCacheUserInfoReqDTOreq) {//1. Caching user informationCacheUser req); CacheAuth req. GetUid), req. GetRoles), req. GetPermissions));//2. Update the relationship between token and userIdStringuserTokenRelationKey=RedisKeyHelper. GetUserTokenRelationKey req. GetEntId)+SymbolConstant. COLON+req. GetUid)); RedisAdapterSetuserTokenRelationKey, req. GetToken), RedisTtl. USER)_ LOGIN_ SUCCESS);}
2. Filter Configuration
The login authentication section and user login status context are not within the scope of this article and are ignored here.
It is best to configure count to limit scan and ensure performance
@OverridesProtected Mono<Void> innerFilterServerWebExchange exchange, WebFilterChain chain) {StringToken=filterContext. GetToken);If StringUtils.isBlanktoken)) { Throw NewDataValidateException GatewayReturnCodes. TOKEN_MISSING);}//Scan obtains the user's key StringUserKey=""; Set<String≫ Scan=redisAdapter. scan GatewayRedisKeyPrefix. USER_KEY. GetKey))+*+Token);If scan.isEmpty)) { Throw New DataValidateExceptionGatewayReturnCodes.TOKEN_EXPIRED_LOGIN_SUCCESS); } UserKey=scan.iterator).next); MyUser myUser = MyUser) redisAdapter.GetuserKey); IfmyUser==Null) { Throw NewBusinessException GatewayReturnCodes. TOKEN_EXIRED_LOGIN_SUCCESS);}//Insert user information into the httpheader //Dosomething Return chain.filterexchange.mutate).requestNewServerHttpRequest).build)); }
This ensures that even If multiple devices log in simultaneously, they can still obtain login information and context.
3. How to force offline?
In fact, it is also very simple. Before logging in, you can perform verIfication through AOP. If you have already logged in, clear the session or user cache here, and then continue with normal login. Simply put, you can directly add verIfication in the login service
Core logic
StringuserTokenRelationKey=RedisKeyHelper. GetUserTokenRelationKey req. GetEntId)+SymbolConstant. COLON+userEntListGet0).GetUserId)); String redisToken = String) redisAdapter.GetuserTokenRelationKey);If StringUtils.isNotEmptyredisToken) && !redisToken.Equalstoken)) {Throw New BusinessExceptionUserReturnCodes.MULTI_DEVICE_LOGIN); }
This is used to determine if there is already a login and return it to the front-end prompt. Used for other front-end business processing. If there is no need to prompt the front-end and return to the front-end, clear the session or user cache logic directly.
String userTokenRelationKey = RedisKeyHelper.GetUserTokenRelationKeyreq.GetEntId) + SymbolConstant.COLON + userEntity.GetId)); //Obtain the login token of the current user String redisToken = String) redisAdapter.GetuserTokenRelationKey); //Log in all before logging off the line Response<Void> exitLoginResponse = gatewayRpc.allExitExitLoginReqDTO.builder).tokenredisToken).userIduserEntity.GetId)).build));
4. Demo
- Demo Force Offline
Here, I will use the user ID of 4 as a demonstration. First, I will log in normally for the first time, indicating success, and there is one user record in Redis
Login again, I have returned it to the front-end for processing, so there will be a prompt message.
Front end effect
Finally, to expand, what would you do if you wanted to implement scenarios such as mandatory modification of default passwords and login time limits after logging in?
Author: Temporary Worker
Link:
https://juejin.cn/post/7258155447831920700
Source: Rare earth mining gold
Disclaimer: The content of this article is sourced from the internet. The copyright of the text, images, and other materials belongs to the original author. The platform reprints the materials for the purpose of conveying more information. The content of the article is for reference and learning only, and should not be used for commercial purposes. If it infringes on your legitimate rights and interests, please contact us promptly and we will handle it as soon as possible! We respect copyright and are committed to protecting it. Thank you for sharing.(Email:[email protected])