java后端实现token自动续期,这方案有点优雅

实现原理


token自动续期的实现原理如下:

  1. 登录成功后将用户生成的token 作为key、value存储到cache缓存里面 (这时候key、value值一样),将缓存有效期设置为 token有效时间的2倍。

  2. 当该用户再次请求时,通过后端的一个Filter 校验前端token是否是有效token,如果token无效表明是非法请求,直接抛出异常即可;

  3. 根据规则从cache缓存中取出token,判断cache token是否存在,此时有以下几种情况:

  • cache token 不存在

这种情况说明token在缓存中过期了,表明该用户账户空闲时间过长,此时属于正常过期,后端直接返回用户信息已失效,请重新登录即可。

  • cache token 存在,则需要使用jwt工具类验证该cache token 是否过期超时,不过期无需处理。过期则表示该用户一直在操作只是token失效了,后端程序会给token对应的key映射的value值重新生成 token并覆盖value值,该缓存生命周期重新计算。

实现逻辑的核心原理:

前端请求Header中设置的token保持不变,校验有效性以缓存中的token为准。

代码实现(伪码)


  1. 登录成功后给用户签发token,并设置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) {

//设置token有效期为30分钟

Date date = new Date(System.currentTimeMillis() + 30 * 60 * 1000);

//使用HS256生成token,密钥则是用户的密码

Algorithm algorithm = Algorithm.HMAC256(secret);

// 附带username信息

return JWT.create().withClaim(“username”, username).withExpiresAt(date).sign(algorithm);

}

  1. 将token存入redis,并设定过期时间,将redis的过期时间设置成token过期时间的两倍

Sting tokenKey = “sys:user:token” + token;

redisUtil.set(tokenKey, token);

redisUtil.expire(tokenKey, 30 * 60 * 2);

//将token返回给前端用户

return token;

  1. 前端调用后端接口时在请求头中添加token(略)

  2. 过滤器校验token,校验token有效性

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

//从header中获取token

String token = httpServletRequest.getHeader(“token”)

if(null == token){

throw new RuntimeException(“illegal request,token is necessary!”)

}

//解析token获取用户名

String username = JwtUtil.getUsername(token);

//根据用户名获取用户实体,在实际开发中从redis取

User user = userService.findByUser(username);

if(null == user){

throw new RuntimeException(“illegal request,token is Invalid!”)

}

//校验token是否失效,自动续期

if(!refreshToken(token,username,user.getPassword())){

throw new RuntimeException(“illegal request,token is expired!”)

}

}

  1. 实现token的自动续期

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)) {

// 校验token有效性,注意需要校验的是缓存中的token

if (!JwtUtil.verify(cacheToken, userName, passWord)) {

String newToken = JwtUtil.sign(userName, passWord);

// 设置超时时间

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 {

// 根据密码生成JWT效验器

Algorithm algorithm = Algorithm.HMAC256(secret);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值