token刷新

private static final Logger logger = LoggerFactory.getLogger(LoginTools.class);
    /**
     * 用户token,eg. token:1245637858
     */
    private final static String TOKEN_KEY = "token:%s";
    /**
     * 在多长时间内用户不用再次登录,比如3月1日登录了,expires为7天,那么用户
     * 在3月8日之前都不用重新登录
     */
    private final static long TOKEN_REFRESH_EXPIRE_SECONDS = 60*60*24*7;
    private static BaseRedisTools redisTools;
    @Autowired(required = false)
    private BaseRedisTools baseRedisTools;


    /**
     * 用户登录,生成token,
     * token有效期为两个小时,将该token存入redis中,
     * key为id,value为token,该key的有效期设置为7天,
     * 并将token返回给前端,解决token自动续期问题。
     *
     * @param userId 登录用户的唯一表示,eg.'token:123456'
     * @param token  登录用户的token(不一定是token,但是一定只能代表一个用户的信息,用token可以获取到一些信息)
     * @data 2021/4/15 10:48
     * @author zhaojin
     */
    public static String setTokenToRedis(String userId, String token) {
        String key = getRedisKey(userId);
        // 如果oldToken存在且没过期就返回oldToken,否则会导致其他端(用的也是这种刷新方式)的token无法刷新
        // 原因是刷新oldToken的时候需要判断oldToken和redis里存的oldToken是否相同,
        // 相同的话就能刷新,不相同就不能刷新,至于为什么要判断是否相同,请看刷新token逻辑
        String oldToken = (String) redisTools.get(key);
        if (!StringUtils.isEmpty(oldToken) && !TokenTools.isExpired(oldToken)) {
            return oldToken;
        }
        if (!redisTools.set(key, token, TOKEN_REFRESH_EXPIRE_SECONDS)) {
            logger.error("用户登录token存入失败:[userId:{},token:{},expires:{}秒]", userId, token, TOKEN_REFRESH_EXPIRE_SECONDS);
            throw new RuntimeException("登录服务出错");
        }
        return token;
    }

    private static String getRedisKey(String userId) {
        return String.format(TOKEN_KEY, userId);
    }

    public static String refreshTokenByRedis(String token) {
        String userId = TokenTools.getAudience(token);
        String key = getRedisKey(userId);
        Object oldToken = redisTools.get(key);
        // 当前过期token必须和redis里存在的token相同,
        // 要不然只要是个过期的token就能被刷新,存在安全问题
        if (oldToken != null && Objects.equals(token, oldToken)) {
            try {
                Assert.isTrue(!StringUtils.isEmpty(userId), "用户id为空");
                String newToken = TokenTools.getToken(userId, AppConfiguration.APP_LOGIN_SECRET);
                logger.info("用户登录token刷新过期时间,[key:'{}']", key);
                setTokenToRedis(userId, newToken);
                redisTools.expire(key, TOKEN_REFRESH_EXPIRE_SECONDS);
                return newToken;
            } catch (Exception e) {
                logger.warn("用户登录token已过期,重新生成token错误:[key:{},oldToken:{},expires:{}秒]",
                        key, oldToken, TOKEN_REFRESH_EXPIRE_SECONDS);
                throw new TokenAgainLoginException();
            }
        } else {
            logger.info("用户登录token已过期,并长时间未操作,需要重新登录:[key:'{}',expires:'{}秒']", key, TOKEN_REFRESH_EXPIRE_SECONDS);
            throw new TokenAgainLoginException();
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值