Spring Security OAuth2客户端凭证模式添加额外请求参数问题
解决方案:在Client Credentials授权的Token请求中添加自定义参数
要在Spring Security OAuth2的client_credentials授权请求中添加account_id这类额外参数,核心是自定义ClientCredentialsTokenResponseClient来扩展默认的Token请求参数,具体步骤如下:
1. 创建自定义的Token响应客户端
继承DefaultClientCredentialsTokenResponseClient,重写prepareTokenRequest方法,在原有标准参数基础上添加自定义参数:
import org.springframework.security.oauth2.client.endpoint.DefaultClientCredentialsTokenResponseClient; import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; import org.springframework.util.MultiValueMap; public class CustomClientCredentialsTokenResponseClient extends DefaultClientCredentialsTokenResponseClient { private final String accountId; public CustomClientCredentialsTokenResponseClient(String accountId) { this.accountId = accountId; } @Override protected MultiValueMap<String, String> prepareTokenRequest(OAuth2ClientCredentialsGrantRequest grantRequest) { // 获取默认的请求参数(grant_type、client_id、client_secret) MultiValueMap<String, String> parameters = super.prepareTokenRequest(grantRequest); // 添加自定义的account_id参数 parameters.add("account_id", accountId); return parameters; } }
2. 修改OAuth2授权客户端管理器配置
在WebClientConfig中,将自定义的Token响应客户端绑定到ClientCredentials授权提供者:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager; 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.service.OAuth2AuthorizedClientService; import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class WebClientConfig { // 从配置文件注入account_id,也可根据业务需求动态获取 @Value("${custom.oauth2.account-id}") private String accountId; @Bean public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) { // 初始化自定义Token响应客户端 CustomClientCredentialsTokenResponseClient tokenResponseClient = new CustomClientCredentialsTokenResponseClient(accountId); // 构建授权提供者并绑定自定义客户端 OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials(configurer -> configurer.tokenResponseClient(tokenResponseClient)) .build(); AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } @Bean public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager) { ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); // 注意与application.yml中registration的id保持一致(custom-client) oAuth2Filter.setDefaultClientRegistrationId("custom-client"); return WebClient.builder() .filter(oAuth2Filter) .baseUrl(apiUrl) .build(); } }
3. 在配置文件中添加自定义参数
在application.yml中补充account_id的配置项:
custom: oauth2: account-id: 123456789 spring: security: oauth2: client: registration: custom-client: provider: custom-client client-id: xxxxxxxxxxxxxxx client-secret: xxxxxxxxxxxxxxx authorization-grant-type: client_credentials client-authentication-method: post provider: custom-client: token-uri: xxxxxxxxxxxxxxxxxxxxxxxxxx/token
关键注意事项
- 确保
setDefaultClientRegistrationId的参数与yml中registration的id完全匹配(之前代码中的customclient需修正为custom-client) - 若
account_id需动态获取(比如从请求上下文),可通过扩展OAuth2ClientCredentialsGrantRequest或结合SecurityContext传递参数,需根据业务场景调整逻辑
内容的提问来源于stack exchange,提问作者mwhere
相关产品推荐
相关产品推荐

