目录
1 前言
在我们使用JWT令牌进行登录验证的时候,不可避免的也会出现一些问题。比如:当用户修改密码后,旧的令牌仍然生效。因此,我们可以采用Redis进行登录的优化。
2 实现步骤
2.1 软件环境准备
2.1.1 Redis的安装
百度网盘的链接如下,解压即可使用
链接:https://pan.baidu.com/s/1nAXT6alX-pMxxSfAe6-tsw?pwd=0529
提取码:0529
2.1.2 在pom.xml中添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在添加依赖后,会自动向IOC容器中注入StringRedisTemplate对象,通过它我们可以对Redis数据库进行相关操作。
2.1.3 在application.yml中进行相关配置
#redis初始状态没密码,所以暂时不需要配置
spring:
data:
redis:
port: 6379 #端口号
host: localhost #本地
database: 0 #redis有16个小库,默认0
2.2 StringRedisTemplate的常用方法
2.2.1 获取operations
@Autowired
private StringRedisTemplate stringRedisTemplate;
//其它
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
2.2.2 主要方法
相关方法 | 作用 | 参数 |
---|---|---|
operations.set("xx", "xx", 1, TimeUnit.HOURS);//过期时间为1小时 | 向Redis中插入键值均为xx的数据 | 1.键(String) 2.值(String) 3.过期时间数(long) 4.时间数单位(TimeUnit.xx) 注:3和4可以不要 |
operations.get("xx"); | 从Redis中获取键为xx的值 | 键(String) |
operations.getOperations().delete("xx"); | 删除Rdis键为xx的键值对 | 键(String) |
2.3 令牌主动失效机制
2.3.1 登录时将令牌存入Redis
public class UserController {
@PostMapping("/login")
public Result<String> login(//其它) {
//其它代码
//获得JWT令牌
String token = JwtUtil.genToken(claims);
//将JWT令牌存入Redis
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
//过期时间要和JWT令牌保持一致
operations.set(token, token, 1, TimeUnit.HOURS);
}
//其它代码
}
2.3.2 修改密码时删除旧的令牌
public class UserController {
//其它代码
@PatchMapping("/updatePwd")
//@RequestHeader(name = "Authorization") String token从请求头中获取JWT令牌
public Result updatePwd(@RequestBody Map<String, String> params, @RequestHeader(name = "Authorization") String token) {
//其它代码
//删除Redis中旧的JWT令牌
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.getOperations().delete(token);
}
}
2.3.3 拦截器中进行检验
public class LoginInterceptor implements HandlerInterceptor {
//其它
@Override
public boolean preHandle(//其它) {
try {
//其它代码
//没获取到值则不放行
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
if (operations.get(token) == null) {
throw new RuntimeException();
}
//放行
return true;
} catch (Exception e) {
//不放行
return false;
}
}
}