preface
How to kick someone offline in Java? Disable an account and immediately drop its session!
Was simply describe the kick off the business scenarios and implementation scheme, thought that lead to so many bosses sprayed the younger brother don’t open your eyes, in order to avoid you continue to spray, I then write this article, thoroughly clear under various scenarios kicking offline design train of thought, if there is any deficiencies still, every brother please light spray!
Well, without further ado, the text begins
The body of the
If the analogy of kicking people off the line is to tear down a house, then before learning to tear down a house, we must understand how the house is built up, different build method corresponding to different demolition method, can not be confused
For most systems at present, there are two main login modes: traditional Session mode and JWT token mode
Traditional Session mode
Let’s take Session mode as an example. How does this mode work?
(Note: Session refers not only to HttpSession, but to any means of using the server to control sessions.)
Instead of using any framework, we’ll start with the underlying logic.
First, you need a global interceptor that intercepts all session requests, permits if the session is logged in, and forces the session directly to the login interface if it is not logged in
- In the login interface, we need to accept two parameters:
username + password
, take these two parameters to the database to get data - If no data is found, return directly
The user name or password is incorrect
If the data can be found, log in - Using an algorithm (such as uUID), generate a random string like this:
623368f0-ae5e-4475-a53f-93e4225f16ae
This is our token - Now we need to do two things, one is to build this
token
withUserId
The second is to take thistoken
Back to the front end- Set up the mapping: in
Redis
To add a piece of data, ifuserId=10001
So we need toRedisUtil.set("623368f0-ae5e-4475-a53f-93e4225f16ae", 10001)
- will
token
Pass it to the front desk. You can put itCookie
Or just put it inReturns the body body
In the
- Set up the mapping: in
- Session login complete! In the global interceptor, we don’t recognize userids, we recognize tokens, who holds them
623368f0-ae5e-4475-a53f-93e4225f16ae
This token, who isThe user 10001
! - A session access comes in and there is
token
If the token is valid, the session is allowed. No? Go log in!
At this point, it is easy to see that there are two requirements for a client to maintain session logins:
- This client holds
token
- this
token
Is a validtoken
, that is: can be fromRedis
To find the correspondingUserId
And we want to do kick a person offline, must choose at least one of these two start.
First let’s be clear: we cannot clear a token that has been issued to a client unless the client logs out.
(Except Cookie clearing technology and WebSocket real-time push technology can be done, but these two technologies require the active cooperation of the client, we now assume that the client refuses to cooperate, we need to force it offline.)
For now, we can only start with the second point: clear the mapping between this token and the UserId
You might think, this isn’t easy, right? Redis can clear a key in a single line of code.
If we were to kick out user 10001, normally we wouldn’t be able to find out which token is the key based on 10001 alone
To solve this problem, we have to store a copy of UserId -> token mapping. You can store it in a database or in Redis. For performance reasons, we use Redis
Now that things are easier, there are only two steps we need to take to kick someone offline:
- find
Account 10001
The correspondingtoken
The key value - Delete the key
OK, kicked out successfully. When this account visits the system next time, although it carries the token, it has become invalid. Please go to login!
Now you might say:
Is this it? I create a collection of all accounts to be kicked offline, and each time the interceptor determines whether the session is in the collection.
Slow down, please! This is the second mode ———— blacklist mechanism, and read on
JWT mode
The login procedure in JWT mode is not very different from that in traditional Session mode, so it will not be described here
The difference is that when JWT logs in, no session information is stored on the server, and all user parameters are written into the TOKEN generated by JWT
(That’s why JWT tokens grow so long! Usually two or three hundred characters in length)
Whether a session is valid depends on whether the token carried by the session can parse the data properly.
This means that the legitimacy of the token is self-explanatory, not determined by the server!
Therefore, compared with the traditional Session mode, JWT has much weaker control over tokens and cannot proactively clear the token -> UserId mapping
Unless you manually replace the algorithm key for JWT token generation, this will cause all tokens in the system to be invalid and all users to go offline together! This will never do.
So what? Can’t I just kick someone offline?
In fact, the method is certain, as long as the thought does not slide, the method is always more than difficult!
That is to use the blacklist mechanism: to kick out a user, we just need to put his or her UserId or JwT-token into a blacklist, and then we check each request token or UserId in the interceptor to see if it is in the blacklist.
How is this better than the traditional Session model? To each his own!
Blacklist mechanism saves performance in storage, in interceptor one more step blacklist detection step, waste performance!
But frankly speaking, this little bit of performance waste for the current CPU is drizzle, can be directly ignored!
digression
One of my colleagues’ projects provided me with an alternative approach to JWT kicking people offline:
When generating a JWT token, add a fixed parameter as the token generation factor. If you want to kick a user off the line, just change the value of the factor and check in the interceptor each time to see if the token generated by the factor matches the token passed by the client! Check if the token is blocked!
This mode provides a novel logical algorithm, but strictly speaking, it still belongs to the Session mode because the Session authentication is completed by the server storing certain data. I will not go into details here.
Code implementation scheme?
Said so many theories, is always to code, because the author in addition to the SA-Token framework did not find any framework for kicking people offline has a direct ready-made solution, so in this temporarily sa-Token framework as an example
- First add the POM.xml dependency
<! -- Sa-Token permission authentication//sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.121.</version>
</dependency>
Copy the code
- Write the account ID to the session when the user logs on
@RestController
@RequestMapping("user")
public class UserController {
@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// This is only for example simulation. Real projects need to query data from the database for comparison
if("zhang".equals(username) && "123456".equals(password)) {
StpUtil.setLoginId(10001);
return "Login successful";
}
return "Login failed"; }}Copy the code
- Kick the account with the specified ID offline
// Logs out the session of the specified account. When the session accesses the system again, the NotLoginException exception is thrown. The scenario value is -5
@RequestMapping("kickout")
public String kickout(long userId) {
StpUtil.logoutByLoginId(userId);
return "Kick it out.";
}
Copy the code
Sa-token is a Java lightweight authentication framework
The latter
The article is written in detail will inevitably have omissions, here we also ask for light spray, you can comment on the message pointed out deficiencies
If you feel that the article is written well, please do not hesitate to point a thumbs-up for the article, your support is the biggest power of my update!