【SpringSecurity】十二、集成JWT搭配Redis实现退出登录

文章目录

1、登出的实现思路

这是目前的token实现图:

因为JWT的无状态,服务端无法在使用过程中主动废止某个 token,或者更改 token 的权限。也就是说,目前,一旦 JWT 签发了,就只能等它到过期时间才能作废,即使用户已经退出登录。想实现登出,可以引入Redis:

此时,关于token的校验逻辑就变成了:

总结就是:

① 登陆成功之后把生成JWT存到redis中(同时设置key的TTL和JWT自身过期时间一样)

② 用户退出时,从redis中删除该token

③ 用户每次访问时,先校验jwt是否合法,如果合法再从redis里面取出logintoken:jwt判断这个jwt还存不存在,如果不存在就说是用户已经退出登录了

2、集成Redis

引入redis的依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

配置连接信息:

yaml 复制代码
spring:
  redis:
    host: localhost
    port: 6379
    database: 0
    password: 666666

注入redis操作对象的依赖:

java 复制代码
@Resource
private StringRedisTemplate stringRedisTemplate;

(PS:我们没有创建RedisTemplate对象对应的bean,但这个bean却在我们引入依赖后自动加入到了Spring容器中,即自动装配。)

3、认证成功处理器

修改前一节的认证成功处理器,在向客户端发放token的同时存入redis,key的过期时间和token自身过期时间一致。

java 复制代码
...

@Resource
private StringRedisTemplate stringRedisTemplate;
....
stringRedisTemplate.opsForValue()
	.set("logintoken:"+token,objectMapper.writeValueAsString(authentication),30, TimeUnit.MINUTES);

我这里key设置成了字符串logintoken:后跟token值,value则直接序列化认证对象authentication。

注意过期时间和jwt的过期时间保持一致,jwt过期时间可查看下创建jwt时的withExpiresAt方法。

4、退出成功处理器

添加退出成功处理器,退出后清除redis里存的token

java 复制代码
/**
 * 退出成功处理器,用户退出成功后,执行此处理器
 */
@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    //使用此工具类的对象进行序列化操作
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //从请求头中获取Authorization信息
        String authorization = request.getHeader("Authorization");
        //如果授权信息为空,返回前端
        if(null==authorization){
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json;charset=utf-8");
            HttpResult httpResult=HttpResult.builder().code(-1).msg("token不能为空").build();
            PrintWriter writer = response.getWriter();
            writer.write(objectMapper.writeValueAsString(httpResult));
            writer.flush();
            return;
        }
        //如果Authorization信息不为空,去掉头部的Bearer字符串
        String token = authorization.replace("Bearer ", "");
        //redis中删除token,这是关键点
        stringRedisTemplate.delete("logintoken:"+token);
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        HttpResult httpResult=HttpResult.builder().code(200).msg("退出成功").build();
        PrintWriter writer = response.getWriter();
        writer.write(objectMapper.writeValueAsString(httpResult));
        writer.flush();
    }
}

在安全配置类中配置用户成功退出处理器:

java 复制代码
@Resource
private MyLogoutSuccessHandler myLogoutSuccessHandler;

....
http.logout().logoutSuccessHandler(myLogoutSuccessHandler);
http.csrf().disable(); //禁用跨域请求保护 要不然logout不能访问

5、修改token校验过滤器

修改上一节的token校验器JWTCheckFilter,不再只校验token的合法性,合法时,还要校验服务端redis中是否有相应数据,以判断是否已经登出。

java 复制代码
@Resource
private StringRedisTemplate stringRedisTemplate;

//从redis中获取token
String tokenInRedis = stringRedisTemplate.opsForValue().get("logintoken:" + jwtToken);
if(!StringUtils.hasText(tokenInRedis)){
    printFront(response, "用户已退出,请重新登录");
    return;
}

完整:

6、调试

登录下先:

得到token:

此时,服务端redis:

登出时,token为空:

登出时,token错误:

正常登出:

此时,拿登出的token再请求接口:

相关推荐
旺仔学长 哈哈34 分钟前
Spring Boot 智能停车场管理系统---附源码+数据库文档
数据库·spring boot·后端·智能停车场
ClickHouseDB1 小时前
ClickHouse托管Postgres:OLTP+OLAP,新能力解锁最佳数据平台
java·前端·数据库
数智化管理手记1 小时前
主数据重复、错漏频发?一站式主数据管理平台如何落地?
大数据·运维·数据库·人工智能·数据挖掘
吴声子夜歌2 小时前
MongoDB 4.2——选择片键
数据库·mongodb
天天进步一点点2 小时前
QSqlQuery删除sqlite数据库执行drop数据表报错database table is locked unable to fetch row问题
数据库·oracle·sqlite
音视频工程实战2 小时前
PromptQL 新手入门与实战指南
数据库·sql·算法
清川渡水3 小时前
NL2SQL 的正确打开方式:从「AI 猜 SQL」到「置信度闭环」的工程化落地
数据库·人工智能·sql
TDengine (老段)3 小时前
TDengine Go 与 Rust 连接器 — 高性能异步访问
大数据·数据库·物联网·golang·rust·时序数据库·tdengine
东方佑3 小时前
MA-RMSNorm:打破“缩放换智能”的魔咒,大模型归一化的一次范式革命!
数据库·人工智能·计算机视觉
云和恩墨4 小时前
「云帆计划·长沙站」活动成功举办,云和恩墨与紫薇垣和湖南金悦科技分别签约并授牌,本地伙伴生态建设加速
数据库·科技