Java:token自动续期,使用Gateway过滤器—GlobalFilter

文章目录

  • 前言
  • 一、使用步骤
    • 1.实体user
    • 2.登录AuthController
    • 3.网关GatewayFilter
    • 4.续约TokenService
  • 总结

前言

在系统中,在 token 的有效期内,可以登录使用,并且要求如果一直使用系统,一直保持登录状态,而不是 token 过期就直接退出系统了,所以需要在操作系统时保持对 token 有效期的续期。

本文是以 gateway 网关过滤器功能实现。


提示:以下是本篇文章正文内容,下面案例可供参考

一、使用步骤

1.实体user

  • 在用户的实体类中添加如下几个字段
private Integer expireTime;	// 登录超时时间,单位min,此为数据库存的,用户可以自由设置过期时间(按需操作)
private Long loginTime;		// 登录时间
private Long failureTime;	// 过期时间
private String token;		// 用户唯一标识

2.登录AuthController

public class AuthController {

	private static final long MILLIS_SECOND = 1000;
    private static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
    @Autowired
    private RedisUtil redisUtil;
    
	@PostMapping("/login")
    public R login( HttpServletRequest request, @RequestBody AuthUser user){
        // 验证用户名密码、验证码、登录次数、禁用账号等代码省略...
        // userEntity为数据库查询出来的用户信息
        // 登录超时时间,数据库获取,如无此需求,可规定 30min过期即可
        Integer expireTime = userEntity.getExpireTime();	
        userEntity.setLoginTime(System.currentTimeMillis());
        userEntity.setFailureTime(userEntity.getLoginTime() + expireTime * MILLIS_MINUTE);
        userEntity.setToken(request.getSession().getId());	// 使用uuid等唯一标识即可
        //放入缓存
        redisUtil.set("token_" + request.getSession().getId(),
                JSON.toJSONString(userEntity), expireTime, TimeUnit.MINUTES);
        return R.ok().setObj(request.getSession().getId());
    }
}

3.网关GatewayFilter

  • 其中一些代码已省略,只保存了续约token的代码:tokenService.verifyToken(user);
@Slf4j
@Order(-1)		// 保证请求必经此代码
@Component
public class GatewayFilter implements GlobalFilter {
    @Autowired
    private TokenService tokenService;
    
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        HttpHeaders headers = exchange.getRequest().getHeaders();
        List<String> tokenList = headers.get("Access-Token");
        ServerHttpRequest request = exchange.getRequest();
        String url = request.getURI().getPath();
        // 其中一些代码已省略,只保存了续约token的代码
        String user = (String) redisUtil.get("token_" + tokenList.get(0));
        if (!StringUtils.isEmpty(user)) {
        	// 自动刷新缓存
            tokenService.verifyToken(user);
        }
    }
}

4.续约TokenService

/**
 * @author wangrui
 * @date 2024/1/19
 * @description token
 **/
@Component
@Slf4j
public class TokenService {

    @Autowired
    private RedisUtil redisUtil;

    private static final long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
    private static final long MILLIS_SECOND = 1000;
    private static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
    private static final String TOKEN = "token_";

    /**
     * 验证token
     * @param user user的json字符串,看具体存的啥就取啥,解析成所需要的user即可
     */
    public void verifyToken(String user) {
        UserEntity userEntity = JSONObject.parseObject(user).toJavaObject(UserEntity.class);
        long failureTime = userEntity.getFailureTime();
        long currentTime = System.currentTimeMillis();
        // 如果有效期小于20min则续约token
        if (failureTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshToken(userEntity);
        }
    }

    /**
     * 刷新token有效期
     * @param userEntity u
     */
    public void refreshToken(UserEntity userEntity) {
        userEntity.setLoginTime(System.currentTimeMillis());
        userEntity.setFailureTime(userEntity.getLoginTime() + userEntity.getExpireTime() * MILLIS_MINUTE);
        // 刷新缓存
        redisUtil.set(TOKEN + userEntity.getToken(),
                JSON.toJSONString(userEntity), userEntity.getExpireTime(), TimeUnit.MINUTES);
    }
}

总结

清浅时光,心有明媚,处处温暖,情有阳光,时时灿烂。当内心充满祥和,在哪里都是一样欢喜自在;当内心充满智慧,一花一草尽显法身。若能放下心中的执着与挑剔,那么你相逢的一切,皆是美好。

在这里插入图片描述