用户认证后Spring Authorization Server的token端点返回404问题
问题描述
搭建采用密码授权(password grant)模式的Spring Authorization Server时,用户认证流程已成功完成,但请求token端点oauth/token?grant_type=password&username=admin&password=password&scope=read返回404状态码,调试日志显示请求最终跳转到/error端点。
配置代码
@Configuration @EnableWebSecurity public class AuthorisationServerConfig { private final RSAProperties rsaProperties; AuthorisationServerConfig(final RSAProperties rsaProperties){ this.rsaProperties=rsaProperties; } @Bean public RegisteredClientRepository registeredClientRepository() { RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) .clientId("client") .clientSecret("{noop}secret") .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.PASSWORD) .scope("read") .build(); return new InMemoryRegisteredClientRepository(registeredClient); } @Bean public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity httpSecurity) throws Exception { //@formatter:off httpSecurity .authorizeHttpRequests(ar->ar.anyRequest().authenticated()) .csrf().disable() .httpBasic(); //@formatter:on return httpSecurity.build(); } private static KeyPair generateRsaKey() throws NoSuchAlgorithmException { KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); keyPairGenerator.initialize(2048); return keyPairGenerator.generateKeyPair(); } @Bean public AuthorizationServerSettings providerSettings() { return AuthorizationServerSettings.builder() .issuer("http://localhost:9090") .build(); } @Bean public JWKSource<SecurityContext> jwkSource() { RSAKey rsaKey = new RSAKey.Builder(rsaProperties.publicKey()).privateKey(rsaProperties.privateKey()).build(); JWKSet jwkSet = new JWKSet(rsaKey); return (jwkSelector, securityContext) -> jwkSelector.select(jwkSet); } @Bean public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) { return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource); } @Bean public UserDetailsService users() { UserDetails user = User.withDefaultPasswordEncoder() .username("admin") .password("password") .roles("USER") .build(); return new InMemoryUserDetailsManager(user); } }
日志信息
o.s.security.web.FilterChainProxy : Securing POST /oauth/token?grant_type=password&username=admin&password=password&scope=read o.s.s.a.dao.DaoAuthenticationProvider : Authenticated user o.s.s.w.a.www.BasicAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=admin, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_USER]] o.s.security.web.FilterChainProxy : Secured POST /oauth/token?grant_type=password&username=admin&password=password&scope=read o.s.security.web.FilterChainProxy : Securing POST /error?grant_type=password&username=admin&password=password&scope=read o.s.security.web.FilterChainProxy : Secured POST /error?grant_type=password&username=admin&password=password&scope=read
项目依赖
plugins { java id("org.springframework.boot") version "3.0.1" id("io.spring.dependency-management") version "1.1.0" } dependencies { implementation("org.springframework.boot:spring-boot-starter") implementation("org.springframework.security:spring-security-oauth2-authorization-server:1.0.0") implementation("org.springframework.boot:spring-boot-autoconfigure-processor") testImplementation("org.springframework.boot:spring-boot-starter-test") }
问题原因及解决方案
1. 缺少Authorization Server专属SecurityFilterChain配置
当前仅配置了通用的defaultSecurityFilterChain,但未设置专门处理OAuth2端点的SecurityFilterChain。Spring Authorization Server需要优先级更高的专属FilterChain来识别并处理/oauth2/token等端点。
添加以下配置:
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); return http.formLogin(Customizer.withDefaults()).build(); }
2. 端点路径错误
Spring Authorization Server 1.0.0的token端点默认路径为/oauth2/token,而非旧版OAuth2的/oauth/token,请求路径不匹配导致404。
将请求路径修改为/oauth2/token?grant_type=password&username=admin&password=password&scope=read。
3. 缺失Web环境依赖
当前依赖仅包含spring-boot-starter,缺少Web环境支持,无法处理HTTP请求。需添加:
implementation("org.springframework.boot:spring-boot-starter-web")
总结
按以下步骤修改后重新启动服务:
- 添加优先级最高的Authorization Server SecurityFilterChain
- 将请求端点改为
/oauth2/token - 引入
spring-boot-starter-web依赖
完成后再次请求token端点即可正常获取Token。
内容的提问来源于stack exchange,提问作者Dharmvir Tiwari
相关产品推荐
相关产品推荐

