基于Spring的OAuth 2.0客户端认证适配问题(使用apiKey和apiSecret)
基于Spring的OAuth 2.0客户端认证适配问题(使用apiKey和apiSecret)
嘿,我懂你现在的处境——Spring Security OAuth2默认的客户端认证流程用的是client_id和client_secret参数,但你需要适配的是apiKey和apiSecret的格式,刚好我之前处理过类似的场景,给你一步步拆解解决方案:
首先咱们先明确你的需求:要发送一个application/x-www-form-urlencoded格式的POST请求,携带apiKey和apiSecret参数到指定URL换取Bearer Token,这和标准的client_secret_post模式核心逻辑一致,只是参数名不同,所以咱们只需要自定义请求参数的转换逻辑就行。
1. 自定义请求参数转换器
咱们需要重写Spring OAuth2默认的请求实体转换器,把默认的client_id/client_secret替换成apiKey/apiSecret:
import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequest; import org.springframework.security.oauth2.client.endpoint.OAuth2ClientCredentialsGrantRequestEntityConverter; import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; public class CustomClientCredentialsGrantRequestEntityConverter extends OAuth2ClientCredentialsGrantRequestEntityConverter { @Override protected MultiValueMap<String, String> createParameters(OAuth2ClientCredentialsGrantRequest grantRequest) { // 创建自定义参数映射 MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>(); // 将ClientRegistration中的clientId映射为apiKey parameters.add("apiKey", grantRequest.getClientRegistration().getClientId()); // 将ClientRegistration中的clientSecret映射为apiSecret parameters.add("apiSecret", grantRequest.getClientRegistration().getClientSecret()); // 保留授权类型参数 parameters.add(OAuth2ParameterNames.GRANT_TYPE, grantRequest.getGrantType().getValue()); return parameters; } }
2. 配置OAuth2客户端管理器
接下来需要把这个自定义转换器注入到Spring的OAuth2客户端流程中,以RestTemplate为例,配置如下:
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.endpoint.DefaultClientCredentialsTokenResponseClient; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; @Configuration public class OAuth2ClientConfig { @Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { // 创建Token响应客户端,并设置自定义转换器 DefaultClientCredentialsTokenResponseClient tokenResponseClient = new DefaultClientCredentialsTokenResponseClient(); tokenResponseClient.setRequestEntityConverter(new CustomClientCredentialsGrantRequestEntityConverter()); // 构建客户端授权提供者,指定使用自定义的Token响应客户端 OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials(configurer -> configurer.tokenResponseClient(tokenResponseClient)) .build(); // 初始化授权客户端管理器 DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } }
3. 配置客户端注册信息
最后在配置文件里填写你的认证信息,这里以application.yml为例:
spring: security: oauth2: client: registration: # 自定义客户端名称,可根据需求修改 custom-api-client: client-id: ${your-api-key} # 对应curl中的{key} client-secret: ${your-api-secret} # 对应curl中的{secret} authorization-grant-type: client_credentials provider: custom-api-client: token-uri: ${your-token-url} # 对应curl中的{url}
验证效果
配置完成后,Spring发送的认证请求就会和你提供的curl完全一致:
- 请求方法:POST
- 请求头:
Accept: application/json、Content-Type: application/x-www-form-urlencoded - 请求体:
apiKey={key}&apiSecret={secret}
如果需要额外自定义请求头,也可以在自定义转换器里添加,比如重写convert方法来设置更多请求头。
备注:内容来源于stack exchange,提问作者Stuart




