You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 2.x升级至3.2.4时OAuth2客户端认证方法不兼容问题

Spring Boot 2.x升级至3.2.4后OAuth2客户端认证异常解决

问题现象

升级Spring Boot到3.2.4版本后,OAuth2客户端抛出如下异常:

java.lang.IllegalArgumentException: 此类默认支持`client_secret_basic`、`client_secret_post`和`none`认证方式。客户端[onboarding_service]正在使用[post]方式,请使用受支持的客户端认证方法,或使用`setRequestEntityConverter`提供支持[post]的实例。
    at org.springframework.util.Assert.isTrue(Assert.java:129) ~[spring-core-6.1.5.jar:6.1.5]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Assembly trace from producer [reactor.core.publisher.MonoSubscribeOnCallable] :
    reactor.core.publisher.Mono.subscribeOn(Mono.java:4618)
    org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.authorizeClient(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:487)
Error has been observed at the following site(s):
    *______Mono.subscribeOn ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.authorizeClient(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:487)
    *__________Mono.flatMap ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.lambda$filter$14(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:383)
    *____________Mono.defer ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.filter(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:380)
    *____Mono.switchIfEmpty ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.filter(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:379)
    |_             Mono.map ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.filter(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:386)
    |_         Mono.flatMap ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.filter(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:387)
    |_   Mono.switchIfEmpty ⇢ at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.filter(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:388)
    |_           checkpoint ⇢ Request to GET https://onboarding-api.account- [DefaultWebClient]
    |_   Mono.switchIfEmpty ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.lambda$exchange$11(DefaultWebClient.java:461)
    |_        Mono.doOnNext ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.lambda$exchange$11(DefaultWebClient.java:467)
    |_       Mono.doOnError ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.lambda$exchange$11(DefaultWebClient.java:468)
    |_       Mono.doFinally ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.lambda$exchange$11(DefaultWebClient.java:469)
    |_    Mono.contextWrite ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.lambda$exchange$11(DefaultWebClient.java:475)
    *__Mono.deferContextual ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.exchange(DefaultWebClient.java:443)
    |_         Mono.flatMap ⇢ at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultResponseSpec.bodyToMono(DefaultWebClient.java:572)

异常核心原因:客户端配置的post认证方式不在Spring Security OAuth2客户端默认支持列表中,官方默认仅支持client_secret_basic、client_secret_post和none三种规范认证方式。

解决方案

方案一:调整客户端认证方式配置

将配置中的简写post替换为官方标准的client_secret_post,这是最直接的修复方式。

示例application.yml配置修改:

spring:
  security:
    oauth2:
      client:
        registration:
          onboarding_service:
            client-authentication-method: client_secret_post

方案二:自定义请求实体转换器支持post简写

如果无法修改认证方式配置(比如依赖外部固定配置源),可以自定义转换器兼容post这种简写形式:

1. 实现自定义转换器

import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest;
import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequestEntityConverter;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyInserters;

public class CustomClientCredentialsGrantRequestEntityConverter extends OAuth2ClientCredentialsGrantRequestEntityConverter {
    @Override
    protected BodyInserters.FormInserter<String> populateTokenRequestBody(OAuth2ClientCredentialsGrantRequest grantRequest, BodyInserters.FormInserter<String> body) {
        ClientAuthenticationMethod clientAuthMethod = grantRequest.getClientRegistration().getClientAuthenticationMethod();
        // 兼容简写的post认证方式
        if (ClientAuthenticationMethod.POST.equals(clientAuthMethod) || "post".equals(clientAuthMethod.getValue())) {
            MultiValueMap<String, String> formParameters = new LinkedMultiValueMap<>();
            formParameters.add(OAuth2ParameterNames.GRANT_TYPE, grantRequest.getGrantType().getValue());
            formParameters.add(OAuth2ParameterNames.CLIENT_ID, grantRequest.getClientRegistration().getClientId());
            formParameters.add(OAuth2ParameterNames.CLIENT_SECRET, grantRequest.getClientRegistration().getClientSecret());
            return BodyInserters.fromFormData(formParameters);
        }
        return super.populateTokenRequestBody(grantRequest, body);
    }
}

2. 配置WebClient时注册自定义转换器

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfig {

    @Bean
    public WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        // 设置自定义转换器
        oauth2Filter.setRequestEntityConverter(new CustomClientCredentialsGrantRequestEntityConverter());
        return WebClient.builder()
                .filter(oauth2Filter)
                .build();
    }

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) {
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();
        DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
        return authorizedClientManager;
    }
}

内容的提问来源于stack exchange,提问作者Edgar Ayvazyan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:45:33