1. SpringBoot 集成 redis 示例
在之前实现的登录接口中,用户登录成功后会生成一个令牌响应给浏览器,之后浏览器访问其他接口时,都要携带该令牌,接受拦截器的检验,如果令牌有效就放行,允许访问后续接口,否则拦截该请求。但是,现在存在一个问题,如果密码泄露了,修改密码再次登录时,原有令牌是应该失效的,现在的代码还做不到这一点,拿着修改密码之前的令牌仍然可以访问其他接口,这显然是不合理的。
如何才能做到让令牌主动失效呢?此时就需要用到 redis。
- 用户登录成功后,生成令牌,把令牌响应给浏览器的同时,也向 redis 中存储一份。
- 接下来,浏览器访问服务器的其他资源前,拦截器不仅要校验其携带令牌的合法性,还要从 redis 中获取一份相同的令牌。若获取成功则证明令牌未失效,拦截器放行,否则不放行。
- 用户(因密码泄露等情况)修改密码后,还要把 redis 中旧密码对应的旧令牌删除。(这样,当携带旧令牌访问时,就不能在 redis 中获取到同样的令牌了,本次请求就会被拦截下来)
SpringBoot 集成 redis 步骤:
- 导入 spring-boot-starter-data-redis 起步依赖
- 在 yml 配置文件中, 配置 redis 连接信息
- 调用 API(StringRedisTemplate)完成字符串的存取操作
(1) 导入 redis 依赖坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
(2) 在 yml 配置文件中,配置 redis 的连接信息
(3) 调用 API(StringRedisTemplate)完成 redis 的存取操作(先在一个测试类中编写)
@SpringBootTest//测试类上加该注解后,将来单元测试方法执行之前会先初始化IOC容器
public class RedisTest {//添加了redis起步依赖后,会自动向IOC容器注入一个StringRedisTemplate对象//因此如果要使用StringRedisTemplate对象,就不用手动new了,直接从容器中获取@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testpublic void testSet(){//返回操作的集合ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();//向redis中存数据operations.set("username", "zhangsan");}@Testpublic void testGet(){ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();//从redis中获取一个键值对System.out.println(operations.get("username"));}
}
测试:
redis 的启动程序和客户端:
点击 redis 启动程序,启动 redis:
运行 testSet(),向 redis 存入数据。下面验证已经向 redis 中存入了数据:
方式1:打开 redis 客户端,输入 get username,可以得到 zhangsan,证明已存入数据。
方式 2:运行 testGet(),控制台打印出 zhangsan,证明已经向 redis 中存入数据。
//控制台输出
zhangsan
在向 redis 中存数据时,还可以指定该数据的过期时间。
//15秒后过期,自动从redis中删除
operations.set("id", "1", 15, TimeUnit.SECONDS);
2. 为项目添加令牌主动失效机制
(1) 登录成功后,给浏览器响应令牌的同时,也把该令牌存储到 redis 中
(2) LoginInterceptor 拦截器中,需要校验浏览器携带的令牌,同时需要获取到 redis 中存储的与之相同的令牌
(3) 当用户修改密码成功后,删除 redis 中存储的旧令牌
postman 测试: