You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于Spring的OAuth 2.0客户端认证适配问题(使用apiKey和apiSecret)

基于Spring的OAuth 2.0客户端认证适配问题(使用apiKey和apiSecret)

嘿,我懂你现在的处境——Spring Security OAuth2默认的客户端认证流程用的是client_idclient_secret参数,但你需要适配的是apiKeyapiSecret的格式,刚好我之前处理过类似的场景,给你一步步拆解解决方案:

首先咱们先明确你的需求:要发送一个application/x-www-form-urlencoded格式的POST请求,携带apiKeyapiSecret参数到指定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/jsonContent-Type: application/x-www-form-urlencoded
  • 请求体:apiKey={key}&apiSecret={secret}

如果需要额外自定义请求头,也可以在自定义转换器里添加,比如重写convert方法来设置更多请求头。

备注:内容来源于stack exchange,提问作者Stuart

火山引擎 最新活动