【问题标题】:Webflux - Spring Boot - oAuth2 client with http proxy supportWebflux - Spring Boot - 具有 http 代理支持的 oAuth2 客户端
【发布时间】:2020-02-23 04:46:19
【问题描述】:

我正在努力在代理后面使用 oauth2 正确设置 webflux-weblient。

看来, ServerOAuth2AuthorizedClientExchangeFilterFunction 使用了一个新的 webclient 实例,它不包含我的代理配置。

OAuth2-配置

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

OAuth2AuthorizedClientResolver.class 包含:

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

WebClientReactiveClientCredentialsTokenResponseClient.java 创建一个新的网络客户端如下:

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

是否有人有示例如何为 oauth2 客户端正确设置 http 代理?

【问题讨论】:

  • 你找到解决办法了吗?
  • 你试过@jocker提到的解决方案吗???

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


【解决方案1】:

感谢@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;
    }

希望这会有所帮助。

【讨论】:

    【解决方案2】:

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

    @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
    

    【讨论】:

    • 谢谢,但我在您的示例中看不到任何代理配置...正如问题中提到的那样,这是这里的问题...
    猜你喜欢
    • 1970-01-01
    • 2018-08-22
    • 2016-09-28
    • 2018-11-09
    • 2019-09-26
    • 2017-09-17
    • 2017-09-26
    • 2018-11-10
    • 1970-01-01
    相关资源
    最近更新 更多