Spring Boot3.1.0+OAuth2授权服务器1.1.0自定义Token失效求助
一、OAuth2TokenCustomizer未生效的修复
1. 必须显式注册Customizer到授权服务器配置
在AuthorizationServerConfig中配置tokenSettings时,一定要将自定义的OAuth2TokenCustomizer纳入配置,否则Spring不会自动触发它的逻辑。示例代码:
@Bean public OAuth2AuthorizationServerConfiguration authorizationServerConfiguration( OAuth2TokenCustomizer<JwtEncodingContext> jwtTokenCustomizer) { return OAuth2AuthorizationServerConfiguration.builder() .tokenSettings(tokenSettings(jwtTokenCustomizer)) // 补充客户端、认证端点等其他配置 .build(); } private OAuth2TokenSettings tokenSettings(OAuth2TokenCustomizer<JwtEncodingContext> customizer) { return OAuth2TokenSettings.builder() .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED) .jwtCustomizer(customizer) .build(); }
同时,自定义的Customizer类要添加@Component注解,让Spring能扫描到它;或者直接在配置类中手动声明为Bean。
2. 泛型类型必须匹配
针对JWT类型的Token,Customizer必须使用OAuth2TokenCustomizer<JwtEncodingContext>泛型,否则无法匹配Token生成流程。示例自定义类:
@Component public class CustomJwtTokenCustomizer implements OAuth2TokenCustomizer<JwtEncodingContext> { @Override public void customize(JwtEncodingContext context) { Authentication principal = context.getPrincipal(); // 从认证主体中提取用户名、角色信息 String username = principal.getName(); List<String> roles = principal.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList()); // 将信息写入JWT的claims字段 context.getClaims() .claim("username", username) .claim("roles", roles); } }
3. 确认Token格式为SELF_CONTAINED
如果Token格式设置为REFERENCE(引用式Token),JWT自定义逻辑完全不会生效——因为这种Token只是一个引用ID,并非自包含的JWT结构。必须在tokenSettings中明确指定:
.tokenSettings(OAuth2TokenSettings.builder() .accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED) // 补充过期时间等其他配置 .build())
二、OAuth2AuthorizationService无法自动注入的解决
1. 依赖版本要对应
Spring OAuth2 Authorization Server 1.1.0默认使用InMemoryOAuth2AuthorizationService,如果需要基于数据库存储授权信息,需引入对应JDBC依赖:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-authorization-server-jdbc</artifactId> <version>1.1.0</version> </dependency>
使用内存实现则无需额外依赖,但要确保Spring能自动扫描到默认Bean。
2. 避免手动创建冲突Bean
如果自行定义了OAuth2AuthorizationService的Bean,会覆盖Spring默认实现,大概率导致注入失败。若无需自定义实现,不要手动声明该Bean。
3. 弃用旧版注解
注意:Spring OAuth2 Authorization Server 1.0+已弃用@EnableAuthorizationServer注解,当前通过OAuth2AuthorizationServerConfiguration构建配置。如果配置类仍使用旧注解,会导致Bean加载混乱,进而引发注入失败。正确配置类示例:
@Configuration public class AuthorizationServerConfig { @Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient client = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("your-client-id") .clientSecret("{noop}your-client-secret") .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) .redirectUri("http://localhost:8080/login/oauth2/code/your-client") .scope(OAuth2Scopes.OPENID) .scope("read") .build(); return new InMemoryRegisteredClientRepository(client); } // 补充Token、认证端点等其他配置 }
三、额外检查点
- 确保用户认证逻辑中,
Authentication对象包含正确的用户名和角色信息。比如WebSecurityConfig中的UserDetailsService要返回带角色的UserDetails:
@Bean public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("test-user") .password("{noop}test-pass") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); }
- 检查自定义的
SecurityFilterChain是否正确放行授权服务器的核心端点(如/oauth2/token、/oauth2/authorize等),若被拦截会导致Token生成流程异常。
内容的提问来源于stack exchange,提问作者Abhinav Prakash

