spring security oauth2的redistokenstore在spring boot 2.0+中默认不可用,需显式引入spring-security-oauth2依赖(如2.5.2.release),并确保授权服务器与资源服务器共用同一redistokenstore实例,同时注意jdk序列化要求或谨慎替换为jackson序列化策略。

能用,但必须注意版本兼容性与序列化策略——Spring Security OAuth2 的 RedisTokenStore 在 Spring Boot 2.0+ 中默认不可用,需显式引入旧版依赖并规避 Jackson 反序列化陷阱。
为什么直接 new RedisTokenStore(redisConnectionFactory) 会报错
Spring Boot 2.1+ 默认移除了 spring-security-oauth2 模块(已进入维护模式),而 RedisTokenStore 正属于该模块。若只引入 spring-boot-starter-data-redis,编译时就会提示找不到类。
- 错误现象:
java.lang.NoClassDefFoundError: org/springframework/security/oauth2/provider/token/store/RedisTokenStore - 根本原因:Spring Boot 2.x 官方推荐迁移到 Spring Authorization Server(全新项目),但老 OAuth2 项目仍大量存在,必须手动拉回兼容依赖
- 正确做法:在
pom.xml中强制添加spring-security-oauth22.5.2.RELEASE(适配 Spring Boot 2.7.x)或 2.3.8.RELEASE(适配 2.3–2.6)
必须配置的 Maven 依赖组合
仅靠 spring-boot-starter-data-redis 不够,RedisTokenStore 需要完整 OAuth2 TokenStore 接口体系支撑。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 核心依赖(缺一不可):
org.springframework.security.oauth:spring-security-oauth2:2.5.2.RELEASEorg.springframework.boot:spring-boot-starter-data-redis-
redis.clients:jedis或io.lettuce:lettuce-core(推荐 Lettuce,线程安全)
- ⚠️ 注意:不要同时引入
spring-boot-starter-oauth2-resource-server,它和旧 OAuth2 模块冲突 - 若用 Spring Boot 3.x,这条路已彻底废弃,必须改用
spring-authorization-server+ 自定义RegisteredClientRepository和OAuth2TokenRepository
RedisTokenStore 初始化时的两个关键坑
RedisTokenStore 默认使用 JDK 序列化,一旦 Token 对象含非 Serializable 字段(如 Authentication 中的 Principal 实现类未实现 Serializable),就会反序列化失败。
- 典型错误:
java.io.InvalidClassException: failed to read class descriptor或空指针(反序列化后对象为 null) - 解决方案一(推荐):保持 JDK 序列化,但确保所有参与认证的对象(如自定义
UserDetails、Authentication子类)都实现Serializable并声明serialVersionUID - 解决方案二:替换序列化策略,例如注入
JacksonSerializationStrategy,但需手动注册ObjectMapper并配置SimpleModule处理OAuth2Authentication类型 —— 这反而容易引发类型擦除问题,不建议轻试 - 别漏掉前缀配置:生产环境务必设置
setPrefix("oauth2:"),避免和其他业务 key 冲突
授权服务器与资源服务器必须共用同一 TokenStore 实例
很多人只在 AuthorizationServerConfigurerAdapter 中配置 tokenStore,却忘了资源服务器(ResourceServerConfigurerAdapter)也需要用同一个实例校验 token,否则会出现「token 生成了但校验失败」。
- 错误配置:授权服务用
RedisTokenStore,资源服务用默认InMemoryTokenStore - 正确做法:将
RedisTokenStore声明为@Bean,并在两个配置类中@Autowired注入同一实例 - 示例关键代码:
@Bean public TokenStore redisTokenStore(RedisConnectionFactory factory) { RedisTokenStore store = new RedisTokenStore(factory); store.setPrefix("oauth2:"); return store; } - 资源服务器中必须调用
resources.tokenServices(defaultTokenServices()),且defaultTokenServices()内部也得用这个redisTokenStore
真正麻烦的不是写几行配置,而是确认整个调用链上:token 生成、存储、解析、校验,四个环节用的都是同一个 RedisTokenStore 实例,且序列化/反序列化行为完全一致。任何一环脱节,都会表现为「token 无效」或「用户登出后还能访问」这类静默故障。










