Webflux-Spring Boot-具有http代理支持的oAuth2客户端

时间:2019-10-27 18:22:28

标签: spring-security spring-webflux spring-oauth2

我正在努力通过代理后面的oauth2正确设置webflux-weblient。

似乎ServerOAuth2AuthorizedClientExchangeFilterFunction使用了一个webclient的新实例,该实例不包含我的代理配置。

OAuth2-Config

    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2ClientFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
      clientRegistrations,
      new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
   oauth2ClientFilter.setDefaultClientRegistrationId("azure");

OAuth2AuthorizedClientResolver.class包含:

private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();

WebClientReactiveClientCredentialsTokenResponseClient.java创建一个新的Web客户端,如下所示:

private WebClient webClient = WebClient.builder().build();

有人有示例如何为oauth2客户端正确设置http-proxy吗?

2 个答案:

答案 0 :(得分:0)

对于OAuth2.0客户端凭据流,在网络安全配置中,您需要以下内容:

@EnableWebFluxSecurity
public class WebSecurityConfiguration {
  @Bean
  public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
      ReactiveClientRegistrationRepository clientRegistrationRepository,
      ReactiveOAuth2AuthorizedClientService authorizedClientService) {

    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
        ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
            .clientCredentials()
            .build();

    AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
        new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientService);
    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    return authorizedClientManager;
  }
  @Bean
  public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
    return WebClient.builder().filter(oauth).build();
  }
}

现在进行实际的API调用:

webClient.get()
        .uri(<protected resource uri which you want to access>)
        .attributes(clientRegistrationId(<The Provider name specified under registration in app yaml>))
        .retrieve()
        .bodyToMono(String.class)
        .map(string
            -> "Retrieved using Client Credentials Grant Type: " + string)
        .subscribe(LOGGER::info);

供参考,我使用的是Spring Boot版本2.3.1.RELEASE 我的application.yaml看起来像这样:


spring:
  security:
    oauth2:
      client:
        provider:
          <provider-name>:
            issuer-uri: <issuer-uri implementing OIDC>
        registration:
          <provider-name>:
            client-id: <client-id>
            client-secret: <client-secret>
            scope: <comma separated scopes>
            authorization-grant-type: client_credentials

答案 1 :(得分:0)

感谢@abhinaba-chakraborty 的不完整回答,我设法根据 WebClient 内的 JVM 参数为 WebClientReactiveClientCredentialsTokenResponseClient 设置了代理。

这是我的代码片段,可以帮助其他有同样问题的人:

这是一个辅助函数,用于获取 JVM 参数并将它们设置为 HttpClient

    public HttpClient proxyHttpClient() {
        String proxyHost = System.getProperty("https.proxyHost");
        String proxyPort = System.getProperty("https.proxyPort");

        if (proxyHost == null && proxyPort == null) {
            return HttpClient.create();
        }

        return HttpClient.create()
                .tcpConfiguration(tcpClient ->
                        tcpClient.proxy(proxy ->
                                proxy.type(ProxyProvider.Proxy.HTTP).host(proxyHost).port(Integer.valueOf(proxyPort))
                        )
                );
    }

这是如何为用于调用外部系统的 WebClient 配置 OAuth2Client(基于@abhinaba-chakraborty 的响应)。请注意名为 configureHttpProxy 的函数:

    @Bean
    public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
            ReactiveClientRegistrationRepository clientRegistrationRepository,
            ReactiveOAuth2AuthorizedClientService authorizedClientService) {

        return configureHttpProxy(
                new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                        clientRegistrationRepository,
                        authorizedClientService
                )
        );
    }

    @Bean
    WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth2Client.setDefaultClientRegistrationId("registration_id");
        return WebClient.builder()
                .filter(oauth2Client)
                .clientConnector(new ReactorClientHttpConnector(HttpClient.create().wiretap(true)))
                .baseUrl(rdoWebClientProperties.getBaseUrl())
                .defaultHeader(rdoWebClientProperties.getApikeyName(), rdoWebClientProperties.getApikeyValue())
                .build();
    }

这里是 configureHttpProxy 函数:

    private AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager configureHttpProxy(AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        // set the webclient with proxy configuration in the ReactiveOAuth2AccessTokenResponseClient
        WebClientReactiveClientCredentialsTokenResponseClient tokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();
        tokenResponseClient.setWebClient(
                WebClient.builder()
                        .clientConnector(new ReactorClientHttpConnector(proxyHttpClient()))
                        .build()
        );

        // set the ReactiveOAuth2AccessTokenResponseClient with webclient configuration in the ReactiveOAuth2AuthorizedClientProvider
        ClientCredentialsReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsReactiveOAuth2AuthorizedClientProvider();
        authorizedClientProvider.setAccessTokenResponseClient(tokenResponseClient);

        // set the ReactiveOAuth2AuthorizedClientProvider in the ReactiveOAuth2AuthorizedClientManager
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

希望这会有所帮助。