Spring Authorization Server无法添加OAuth2授权码请求认证提供者
你的核心问题是手动指定全局AuthenticationManager覆盖了Spring Authorization Server自动构建的专用AuthenticationManager,导致OAuth2专属认证提供者未被注入到授权请求的过滤器链中。以下是具体修复方案:
1. 移除全局AuthenticationManager的手动绑定
在oauthFilterChain配置中删除这一行:
.authenticationManager(authenticationManager)
Spring Authorization Server的OAuth2AuthorizationServerConfigurer会自动为授权端点、令牌端点创建包含所需认证提供者的专用AuthenticationManager,手动传入全局管理器会覆盖该逻辑,导致OAuth相关Provider丢失。
2. 修正OAuth2AuthorizationCodeRequestAuthenticationProvider的配置位置
你之前错误地将该Provider同时添加到clientAuthentication和authorizationEndpoint中,clientAuthentication有专属的认证提供者(如OAuth2ClientAuthenticationProvider),无需添加授权码请求的Provider。仅在authorizationEndpoint下配置即可:
authorizationServerConfigurer .registeredClientRepository(registeredClientRepository) .tokenGenerator(tokenGenerator) .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint .authenticationProvider(authorizationCodeRequestAuthenticationProvider) ) .tokenEndpoint(tokenEndpoint -> { }) ;
3. 保留全局认证逻辑的说明
如果全局AuthenticationManager中的DaoAuthenticationProvider等需要生效,无需手动绑定整个管理器。Spring Security过滤器链会自动用全局认证管理器处理表单登录等上游认证,授权端点则使用Authorization Server创建的专用管理器处理OAuth2相关请求,两者互不冲突。
完整修正后的oauthFilterChain代码示例
@Bean @Order(103) public SecurityFilterChain oauthFilterChain(HttpSecurity http, JdbcRegisteredClientRepository registeredClientRepository, OAuth2TokenGenerator<?> tokenGenerator, OAuth2AuthorizationCodeRequestAuthenticationProvider authorizationCodeRequestAuthenticationProvider) throws Exception { http .securityMatcher("/oauth/**") .authorizeHttpRequests(auth -> auth .requestMatchers("/oauth/authorize").hasRole("MEMBER") .requestMatchers("/oauth/**").permitAll() ) .sessionManagement(session -> session .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) .sessionFixation(c -> c.none()) // FIXME turn it back on ) // 移除全局AuthenticationManager绑定 .formLogin(form -> form .successForwardUrl("/oauth/authorize") .loginProcessingUrl("/oauth/do_login") .failureUrl("/oauth/login?failure=true") .successHandler(oauthAuthenticationSuccessHandler()) .usernameParameter("username") .passwordParameter("password") .loginPage(OAUTH_LOGIN_VIEW_NAME) ) .exceptionHandling(exception -> exception.authenticationEntryPoint(oauthLoginEntryPoint())) .csrf(withDefaults()) ; OAuth2AuthorizationServerConfigurer authorizationServerConfigurer = new OAuth2AuthorizationServerConfigurer(); http.apply(authorizationServerConfigurer); authorizationServerConfigurer .registeredClientRepository(registeredClientRepository) .tokenGenerator(tokenGenerator) .authorizationEndpoint(authorizationEndpoint -> authorizationEndpoint .authenticationProvider(authorizationCodeRequestAuthenticationProvider) ) .tokenEndpoint(tokenEndpoint -> { }) ; return http.build(); }
验证方式
重启应用后,断点调试OAuth2AuthorizationEndpointFilter的doFilterInternal方法,查看AuthenticationManager的providers列表,即可确认OAuth2AuthorizationCodeRequestAuthenticationProvider已被包含。
内容的提问来源于stack exchange,提问作者Ken DeLong

