Imitate a B's long-term login effective double Token mechanism

Imitate a B's long-term login effective double Token mechanism

提示:需要有一定了解token机制的同学进行学习



Initiate thinking about how a certain B stays in the login state for a long time

Everyone should have used a certain B. I don’t know if the students who use a certain B have found a problem. After logging in to other people’s websites, they will automatically log out after a period of time without using them. However, a certain B, even if you do not use it for a long time, is still in the Login status. And all the websites are as long as you use, and there will be no sudden exit when you use half of them. So for this situation, I have made deep thinking about it. After secretly inquiring about the information, I found that everyone mentioned something called double token.
After using my simple demo, I found that it is really good. There is no plagiarism in the ideas of this article, and most of the ideas and processing are made by my own independent thinking. Don't spray if you don't like it. Thanks.


提示:以下案例可供参考

1. What is Dual Token?

As the name suggests: two tokens, on top of the basic idToken, add a new refreshToken, which
is explained on jwt's official website as: Refresh Tokens

2. Use steps

1. Implementation idea

The idea is really very important. If you don’t get the point of double token, you will not be able to figure out the difference between this and the ordinary single token. This article only shows how you handle the double token of the jwt tool. If there is any similarity, purely It's a coincidence.
After the login request, double tokens are issued and returned to the front end. The reason: the main authentication token is actually the idToken. Only when the short-term token expires and the jwt tool fails to parse the token, the refreshToken will be processed. In practice In the above, the parameters of refreshToken and idToken during production can be the same or different, and the specific logic can be analyzed in detail.
After the double token is transmitted to the backend, the idToken will be verified first. If the idToken has not expired and you can log in successfully, the token will not be refreshed (you can also choose to refresh here, I think it is not necessary). If the idToken expires, then
in A timeout exception will occur during parsing. Just catch the exception and continue parsing the refreshToken. If the refreshToken also has a timeout exception, the interceptor will intercept it and let the user log in again. Here, token exceptions can be handled separately. If the refreshToken continues to be valid, the operation is successful, and the front end can request the token to refresh the interface.
At this time, it may appear that the refreshToken has not expired in the previous second, but the possibility expires when the interface is requested to refresh, then a timeout exception will also occur when jwt parses the body user information. At this time, the interface directly returns the corresponding jump code or proceeds directly. Just jump to the page. The system can no longer refresh the token for the user and can only allow the user to log in again.

Interceptor processing code (example):

The following shortToken represents idToken, and longToken represents refrshToken

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
    
    
        if (!(object instanceof HandlerMethod)) {
    
    
            return true;
        }
        String shortToken = request.getHeader("authorization");// 从 http 请求头中取出 token
        String longToken = request.getHeader("authorization-long");
        log.info("短期token:{}", shortToken);
        log.info("长期token:{}", longToken);
        // 执行认证
        if (null == shortToken && null == longToken) {
    
    
            throw new RuntimeException("无token,请重新登录");
        }
        String phone = null;
        Claims shortTokenClaim = null;
        Claims longTokenClaim = null;
        if (null != shortToken) {
    
    
            try {
    
    
                // 先验证短期token
                shortTokenClaim = tokenObj.getTokenClaim(shortToken);
                phone = shortTokenClaim.getSubject();
                if (null == phone) {
    
    
                    throw new RuntimeException("用户不存在,请重新登录");
                }
                log.info("通过短期token登录成功");
                return true;
            } catch (Exception j) {
    
    
                log.debug("短期token过期,继续检测长期token");
            }
        }

        try {
    
    
            log.info("检查长期令牌加长期令牌时间");
            longTokenClaim = tokenObj.getTokenClaim(longToken);
            phone = longTokenClaim.getSubject();
            if (null == phone) {
    
    
                throw new RuntimeException("用户不存在,请重新登录");
            }
            log.info("通过长期token登录成功,需要刷新token");
        } catch (Exception e) {
    
    
            log.error("长期令牌已失效请重新登录");
            return false;
        }
        return true;
    }

Tool class (example):

package com.mrone.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class JwtUtil {
    
    

    private String secret= "NjYwQ0Y0N0M3ODhFODYwOUU2RDM1RTNDRkNENjQ1REE=";
    private long expire= 3600;
    private String header="token";
    public String getLongTimeToken (String phone){
    
    
        Date nowDate = new Date();
        //过期时间  两天后的这个点
        Date expireDate = new Date(nowDate.getTime() + expire * 1000 * 47);
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(phone)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
    //一分钟后过期
    public String getShortTimeToken (String phone){
    
    
        Date nowDate = new Date();
        Date expireDate = new Date(nowDate.getTime() + expire*100 );
        return Jwts.builder()
                .setHeaderParam("typ", "JWT")
                .setSubject(phone)
                .setIssuedAt(nowDate)
                .setExpiration(expireDate)
                .signWith(SignatureAlgorithm.HS512, secret)
                .compact();
    }
	//刷新Token
    public Map refresh(String auth){
    
    
        Map<String,String> map = new HashMap<>();
        try{
    
    
            String phone = getTokenClaim(auth).getSubject();
            String shortTimeToken = getShortTimeToken(phone);
            String longTimeToken = getLongTimeToken(phone);
            map.put("short",shortTimeToken);
            map.put("long",longTimeToken);
        }catch (Exception e){
    
    
            System.out.println("长期token过期,请重新登录");
            map.put("202","请重新登录");
        }
        return map;
    }

    /*
     * 获取 Token 中注册信息
     */
    public Claims getTokenClaim (String token) {
    
    
        try {
    
    
            return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
        }catch (Exception e){
    
    
            e.printStackTrace();
            return null;
        }
    }

}

Refresh interface (example):

    @ApiOperation(value = "admin",tags = "token刷新")
    @PostMapping("/refresh")
    public Map refresh(HttpServletRequest request){
    
    
        String authorization = request.getHeader("authorization-long");
        return jwtUtil.refresh(authorization);
    }

Summarize

提示:以上内容仅供参考:
If you need a demo case, please private message me.
Mini program address: https://github.com/CaseOfShe/school
Demo address: https://www.bilibili.com/video/BV1q3411g71P

Guess you like

Origin blog.csdn.net/weixin_53690059/article/details/129548583