SpringBoot基于Redis实现token的在线续期

相信很多小伙伴会发现,token这个东西在方便的同时也有一丝丝麻烦(想了解或学习token相关知识请移步:JAVA后端实现JWT令牌_令牌 java-CSDN博客

原因很简单,其实就是token的过期时间究竟设置多久才算合理,一小时太短,一百年又太长。所以在线续期token是一种很好的解决方案,我的实现思路是:取消原先token自己的过期时长,然后将token存入redis中,key是token,value也是token,存进去什么不重要,重要的是可以根据key去获取value(有效并且没过期),需要的时候随时可以取出来,然后给这个redis一个过期时间,众所周知redis的过期时间是可以重置的,因此在用户每次进行操作的时候就重新给redis一个过期时间即可。大概思路就是这样,醍醐灌顶的小伙伴现在就可以自己去试一下!

这是我们之前的实现思路,也就是给token一个过期时间,然后token过期之后销毁。我们现在吧过期时间直接删掉。

我们现在只在token中放入我们需要的载荷信息以及签名算法。

然后我们需要去修改登录的逻辑,以前是生成一个token返回到前端,现在需要添加一步:将token存入redis中。

这样就实现了redis的储存,现在我们实现续期,我们去修改拦截器的逻辑。

以下是我项目中拦截器的代码: 

 public boolean preHandle(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler) throws Exception {
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }

        List<String> asList = Arrays.asList("/login", "/pageHomeImages", "/register", "/doc.html", "/v2", "/swagger-resources/**", "/webjars/**", "/v2/**", "/swagger-ui.html/**");
        String requestUrl = request.getRequestURI();
        log.info("请求的url为:{}", requestUrl);

        if (asList.stream().anyMatch(requestUrl::contains)) {
            log.info("{}-->已放行", requestUrl);
            return true;
        }

        String token = request.getHeader("token");
        log.info("从请求头中获取的令牌:{}", token);

        if (!StringUtils.hasLength(token)) {
            log.warn("Token不存在");
            throw new CustomException(401, Constant.TOKEN_ERROR);
        }

        try {
            if (redisTemplate.opsForValue().get(token) != null) {
                Claims claims = JwtUtils.parseJWT(token);
                ThreadLocalContext.setUserId(claims.get("id").toString());
                redisTemplate.opsForValue().set(token, token, DELAYED_TIME, TimeUnit.SECONDS);
                log.info("{}-->已放行", requestUrl);
                log.info("用户:{}-->token已在线续期一小时", claims.get("id").toString());
                return true;
            } else {
                log.warn("token已过期");
                throw new CustomException(401, Constant.TOKEN_TIMEOUT);
            }
        } catch (Exception e) {
            log.error("token在线续期失败!");
            throw new CustomException(401, Constant.USER_STATUS_ERROR);
        }
    }

 至此已全部完成,只要用户有相关操作,即可实现刷新token的效果,在此基础上,还可以实现类似于获取当前过期时间并在此基础上增加时间等效果。

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用 Spring Boot 基于 Redis 实现分布式锁的示例代码: 首先在 pom.xml 中添加 Redis 相关依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 然后创建一个 Redis 分布式锁的工具类: ```java @Component public class RedisLockUtil { @Autowired private RedisTemplate<String, String> redisTemplate; /** * 尝试获取分布式锁 * @param key 锁的名称 * @param value 锁的值 * @param expireTime 锁的过期时间,单位为秒 * @return 是否成功获取锁 */ public boolean tryLock(String key, String value, long expireTime) { Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, Duration.ofSeconds(expireTime)); return result != null ? result : false; } /** * 释放分布式锁 * @param key 锁的名称 * @param value 锁的值 */ public void unlock(String key, String value) { String currentValue = redisTemplate.opsForValue().get(key); if (StringUtils.isNotBlank(currentValue) && StringUtils.equals(currentValue, value)) { redisTemplate.delete(key); } } } ``` 在上述代码中,我们使用了 RedisTemplate 对 Redis 进行操作,其中 tryLock() 方法尝试获取分布式锁,如果获取成功则返回 true,否则返回 false。unlock() 方法释放分布式锁。 最后,在需要使用分布式锁的地方注入 RedisLockUtil 并使用它进行加锁和解锁,示例如下: ```java @Service public class UserService { @Autowired private RedisLockUtil redisLockUtil; public void updateUser(User user) { String lockKey = "updateUser:" + user.getId(); String lockValue = UUID.randomUUID().toString(); try { boolean lockResult = redisLockUtil.tryLock(lockKey, lockValue, 60); if (lockResult) { // 获取分布式锁成功,执行更新操作 // ... } else { // 获取分布式锁失败,抛出异常或者重试 // ... } } finally { // 释放分布式锁 redisLockUtil.unlock(lockKey, lockValue); } } } ``` 在上述代码中,我们调用 RedisLockUtil 的 tryLock() 方法尝试获取分布式锁,如果获取成功则执行更新操作,否则抛出异常或者重试。最后在 finally 块中调用 RedisLockUtil 的 unlock() 方法释放分布式锁。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值