9.11 从零在项目中落地redis
一.添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
注:如果启动报 redis 配置找不到,把 spring.redis 改成 spring.data.redis 即可。
二.yml配置
spring:
data:
redis:
host: 127.0.0.1//redis运行ip
port: 6379
password: {{你的redis密码}}
timeout: 5000ms//连接超时时间
三.redis的序列化配置
为何要配置呢:默认的 JdkSerializationRedisSerializer 会把 key 序列化成二进制,用 redis-cli keys * 看到的是 \xac\xed\x00...,根本看不清。存 token 这种纯字符串,用 StringRedisSerializer 最干净。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String,String> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
return redisTemplate;
}
}
四.业务中的操作
serviceimpl先注入:
private final RedisTemplate<String, String> redisTemplate;
然后再拿到token后直接存到redis
Long userId = user.get().getId();
String token = jwtUtil.generateToken(userId);
// 存 Redis:key = login:user:{userId},value = token,TTL = JWT 过期时间
String key = "login:user:" + userId;
redisTemplate.opsForValue().set(key, token, expire, TimeUnit.MILLISECONDS);
五.拦截器中进行配置
依旧先注入:
private final RedisTemplate redisTemplate;
原先的逻辑是从request的请求头拿出格式后的token,然后变成原始token,直接解析,最后验完设置Attribute并放行,
现在仅需要改验证步骤,原先是直接由JWTUtil解析,解析成功就行,现在还要验证解析成功后的与redis存的是否一致。具体代码如下:
try {
DecodedJWT decodedJWT = jwtUtil.parseToken(token);//解析token字符串
Long userId = decodedJWT.getClaim("userId").asLong();
String key="login;user:"+userId;
String storedToken = (String) redisTemplate.opsForValue().get(key);
if(storedToken==null||!storedToken.equals(token)){
response.setStatus(401);
response.getWriter().write(objectMapper.writeValueAsString(Result.fail(401, "登录信息异常,请重新登录")));
}
request.setAttribute("userId", userId);
return true;
} catch (TokenExpiredException e) {//捕获token超时异常
response.setStatus(401);
response.getWriter().write(objectMapper.writeValueAsString(Result.fail(401, "TOKEM过期啦,请重新登录哦")));
return false;
} catch (JWTVerificationException e) {//捕获token校验异常
response.setStatus(401);
response.getWriter().write(objectMapper.writeValueAsString(Result.fail(401, "该Token非法哦")));
return false;
}

浙公网安备 33010602011771号