redis 缓存jwt令牌设置更新时间 BUG修复

大家好,今天我又又又来了,hhhhh。

上文中 我们永redis缓存了token 但是我们发现了 一个bug ,redis中缓存的token  是单用户才能实现的。

就是 我 redis中存储的键 名 为token   值 是jwt令牌 ,但是如果 用户a 登录 之后 创建一个 键 为token的 键值对,如果用户b登录,创建的的键名也是 token ,这样用户b的 jwt 会覆盖 用户a的,就会导致 用户a 的token 会失效呀,这真是一个大大的bug , 按照我目前的水平,我想到了一下 的解决方案 ,既然 token 的键会覆盖,那么我们给 token的键 加上一个唯一标识不就好了  

解决前的代码

package com.example.getway.globalfilter;

import cn.hutool.core.collection.CollUtil;
import com.example.getway.Untils.JwtUntils;
import com.example.getway.commen.MessageConstant;
import com.example.getway.pojo.JwtProperties;
import io.jsonwebtoken.Claims;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
@RequiredArgsConstructor
@Slf4j
@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {
    private  final JwtProperties jwtProperties;
    private  final   RedisTemplate redisTemplate;
    // 这个过滤器 请求的转发
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        //我们只要是非登录请求全都要检验jwt 然后进行 用户信息的传递
       //获取request对象
        ServerHttpRequest request = exchange.getRequest();
        RequestPath requestPath = request.getPath();
        if(requestPath.toString().contains("/userLogin")){
            return  chain.filter(exchange);
        }
        //获取请求头的 token
//        String redisToken =null;
//        List<String> authorization = request.getHeaders().get("authorization");
//        if (!CollUtil.isEmpty(authorization)) {
//            redisToken = authorization.get(0);
//        }

        String redisToken = (String)redisTemplate.opsForValue().get(MessageConstant.TOKEN);
        log.info("token:{}",redisToken);
        if (redisToken != null ) {
            //进行jwt的解析
            try {
                Claims claims = JwtUntils.parseJwt(redisToken, jwtProperties.getSecretkey());
                //每次 访问其他资源的时候 都把token更新
                redisTemplate.expire(MessageConstant.TOKEN, 1000, TimeUnit.DAYS);
                String loginId = claims.get(MessageConstant.LOGIN_ID).toString();
                log.info("网关层当前用户的id:{}", Long.valueOf(loginId));
                //证明 token有效 传递用户信息
                ServerWebExchange loginId1 = exchange.mutate()
                        .request(b -> b.header("loginId", loginId))
                        .build();
                return chain.filter(loginId1);
            } catch (Exception e) {
                log.info("{}",e.getMessage());
                //出现异常返回一个异常响应
                ServerHttpResponse response = exchange.getResponse();
                response.setRawStatusCode(401);
                return  response.setComplete();
            }
        }
        log.info("token错误");
       return  exchange.getResponse().setComplete();
    }
//过滤器链中的优先级 数值越低 优先级就越高
    @Override
    public int getOrder() {
        return 0;
    }
}

解决前的登陆代码

package com.example.logindemo.cotroller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.logindemo.Untils.JwtUntils;
import com.example.logindemo.commen.MessageConstant;
import com.example.logindemo.pojo.JwtProperties;
import com.example.logindemo.pojo.po.UserLogin;
import com.example.logindemo.result.Result;
import com.example.logindemo.service.UserLoginService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
@RequiredArgsConstructor
public class LoginController {
    private  final UserLoginService userLoginService;
    private final JwtProperties jwtProperties;
    private  final RedisTemplate redisTemplate;
    @PostMapping("/userLogin")
    public Result userLogin( String username,  String password) {
          password=DigestUtils.md5DigestAsHex(password.getBytes());
        LambdaQueryWrapper<UserLogin> userLoginLambdaQueryWrapper = new LambdaQueryWrapper<UserLogin>()
                .eq(UserLogin::getUsername, username);
        UserLogin userLogin = userLoginService.getOne(userLoginLambdaQueryWrapper);
        if(userLogin==null && userLogin.getUsername().isEmpty()){
            return Result.error("查询不到用户");
        }
        if (username.equals(userLogin.getUsername()) && password.equals(userLogin.getPassword())) {
         //需要一个map集合  传什么 解析出来什么   一般传的是登录用户的id  我们传1
            HashMap<String, Object> map = new HashMap<>();
            map.put(MessageConstant.LOGIN_ID, userLogin.getId());
            String token = JwtUntils.CreateJwt(map, jwtProperties.getSecretkey());
            //设置redis缓存为1000天
            redisTemplate.opsForValue().set(MessageConstant.TOKEN,token,1000,TimeUnit.DAYS);
            return Result.success(token);
        }
        return Result.error("未知错误");
    }

}


解决后 的登录代码  这里只放修改部分

解决后的 网关层过滤代码

现在 我们手动在数据库添加 一个用户  

我们apifox进行登录接口的依次登录 ,然后观察 redis中的缓存数据

 发现token 2 存在  我们也就设置成功了

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

三氧化真

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值