preface

In the separated development mode, the back-end service issues a JWT token to the user after the front-end user logs in successfully. The front-end (such as VUE) stores the JWT token in LocalStorage after receiving it.

Each subsequent request will put the token in the request header and send it to the back-end service. The back-end service will have a filter to intercept and verify whether the token has expired. If the token has expired, the front-end will redirect to the login page to log in again.

JWT tokens generally contain basic user information. To ensure the security of the token, the expiration time of the token is set relatively short.

However, as a result, front-end users need to log in frequently (the token expires), and some forms are complicated. Front-end users need to think for a long time when filling in the form. When the form is actually submitted, the back-end verification finds that the token has expired and is invalid, and they have to jump to the login page.

If that were to happen, the front end users would swear, and the user experience would be very unfriendly. The content of this paper is to realize the automatic renewal of token without the awareness of front-end users, so as to avoid frequent login and loss of form filling contents.

Realize the principle of

The principle of JWT Token automatic renewal is as follows:

  1. Generated by the user after successful loginjwt tokenStore the token as the key and value in the cache (the key and value are the same). Set the cache validity period to twice that of the token.
  2. When the user requests again, it passes through one of the back endsjwt FiltercheckThe front-end tokenCheck whether the token is valid. If the token is invalid, an exception is thrown.
  3. Read the cache token according to the rules to check whether the cache token exists. In this case, the following scenarios are performed:
    • If the cache token does not exist, the user account times out and the returned user information is invalid. Please log in again.
    • If the cache token exists, you need to use the JWT tool class to verify whether the cache token expires. If the cache token does not expire, no action is required. Expired indicates that the user has been operating but the token is invalid. The back-end program will regenerate the JWT token for the value of the key mapping corresponding to the token and overwrite the value. The cache life cycle is recalculated.

The core principle of the implementation logic is as follows: The token set in the front-end request Header remains unchanged, and the verification validity is subject to the token in the cache.

Code implementation (pseudocode)

  1. After successful login, issue a token to the user and set the validity period of the token
. SysUser sysUser = userService.getUser(username,password);if(null !== sysUser){
    String token = JwtUtil.sign(sysUser.getUsername(), 
sysUser.getPassword());
}
...


public static String sign(String username, String secret) {
    // Set the token validity period to 30 minutes
	Date date = new Date(System.currentTimeMillis() + 30 * 60 * 1000);
	// Use HS256 to generate tokens, and the key is the user's password
	Algorithm algorithm = Algorithm.HMAC256(secret);
	// With username information
	return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);
}
Copy the code
  1. Store the token in Redis and set the expiration time to be twice as long as the token
Sting tokenKey = "sys:user:token" + token;
redisUtil.set(tokenKey, token);
redisUtil.expire(tokenKey, 30 * 60 * 2);
Copy the code
  1. Filter verifies token validity
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    // Get the token from the header
	String token = httpServletRequest.getHeader("token")
	if(null == token){
		throw new RuntimeException("Illegal request, token is necessary!")}// Parse the token to obtain the user name
	String username = JwtUtil.getUsername(token);
	// Get the user entity based on the user name, in real development from redis
	User user = userService.findByUser(username);
    if(null == user){
		throw new RuntimeException("Illegal request, token is Invalid!)}// Verify whether the token is invalid and automatically renew the token
	if(! refreshToken(token,username,user.getPassword())){throw new RuntimeException("Illegal Request, token is expired!")}... }Copy the code
  1. Automatic renewal of tokens
public boolean refreshToken(String token, String userName, String passWord) {
	Sting tokenKey = "sys:user:token" + token ;
	String cacheToken = String.valueOf(redisUtil.get(tokenKey));
	if (StringUtils.isNotEmpty(cacheToken)) {
		// Verify the validity of the tokens in the cache
		if(! JwtUtil.verify(cacheToken, userName, passWord)) { String newToken = JwtUtil.sign(userName, passWord);// Set the timeout period
			redisUtil.set(tokenKey, newToken) ;
			redisUtil.expire(tokenKey, 30 * 60 * 2);
		}
		return true;
	}
	return false; }...public static boolean verify(String token, String username, String secret) {
	try {
		// Generate JWT renderers based on the password
		Algorithm algorithm = Algorithm.HMAC256(secret);
		JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();
		/ / a charm TOKEN
		DecodedJWT jwt = verifier.verify(token);
		return true;
	} catch (Exception exception) {
		return false; }}Copy the code

The JWT operations in this article are based on the com.auth0.java-jWT implementation. You can read the original article to obtain the JWTUtil utility class.

summary

The core principle of JWT token implementation logic is that the tokens set in the front-end request Header remain unchanged, and the verification validity is based on the tokens in the cache. Do not directly verify the tokens in the Header. Part of the realization principle we have a good experience, thinking is more important than implementation!


Here for everyone to prepare a small gift, pay attention to the public number, enter the following code, you can get baidu network disk address, no routine to receive!

004: “Internet Architecture Teaching Video” 006: “SpringBoot Implementation of Ordering System” 007: “SpringSecurity combat video” 008: “Hadoop combat teaching video” 009: “Tencent 2019Techo Developer Conference PPT” 010: wechat communication group