【问题标题】:Spring Boot WebClient with OAuth2 and use InsecureTrustManagerFactory带有 OAuth2 的 Spring Boot WebClient 并使用 InsecureTrustManagerFactory
【发布时间】:2021-10-14 18:49:53
【问题描述】:

我已经使用 oAuth2 成功实现了 WebClient。当身份验证服务器 (Keycloak) 具有 SSL (https) 时,oAuth2 面临问题。虽然我在定义 WebClient 时传递了 InsecureTrustManagerFactory,但在构建器完成之前调用了此 oAuth,因为它存在于过滤器中,它使用 WebClient 的默认实现并引发认证错误。

有没有办法我们可以配置 oAuth2 客户端也使用 InsecureTrustManagerFactory?

pom.xml 部分

<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-oauth2-client</artifactId>
    </dependency>

Bean 配置

@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
        final ReactiveClientRegistrationRepository clientRegistrationRepository,
        final ReactiveOAuth2AuthorizedClientService authorizedClientService) {
    logger.info("ReactiveOAuth2AuthorizedClientManager Bean Method");
    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
            .builder().password().build();

    AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
            clientRegistrationRepository, authorizedClientService);

    authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

    authorizedClientManager.setContextAttributesMapper(oAuth2AuthorizeRequest -> Mono
            .just(Map.of(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, System.getProperty("user"),
                    OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, System.getProperty("pass"))));

    return authorizedClientManager;
}

/**
 * The Oauth2 based WebClient bean for the web service
 * 
 * @throws SSLException
 */
@Bean
public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) throws SSLException {

    String registrationId = "bael";

    SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)
            .build();

    SslProvider sslProvider = SslProvider.builder().sslContext(sslContext).build();

    HttpClient httpClient = HttpClient.create().secure(sslProvider)
            .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000).responseTimeout(Duration.ofMillis(5000))
            .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))
                    .addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)));

    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
            authorizedClientManager);
    oauth.setDefaultClientRegistrationId(registrationId);
    logger.info("WebClient Bean Method");
    return WebClient.builder()
            // base path of the client, this way we need to set the complete url again
            .baseUrl("BASE_URL")
            .clientConnector(new ReactorClientHttpConnector(httpClient))
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).filter(logRequest())
            .filter(oauth).filter(logResponse()).build();
}

【问题讨论】:

    标签: spring-boot spring-oauth2 spring-webclient


    【解决方案1】:

    所以你也必须为 OAuth2 创建新的 WebClient。 在您的 authorizedClientManager 定义中添加一些字符串(最好有 HttpClient bean,这样您就不会一直定义它)

    SslContext sslContext = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)
                .build();
    SslProvider sslProvider = SslProvider.builder().sslContext(sslContext).build();
    HttpClient httpClient = HttpClient.create().secure(sslProvider)
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000).responseTimeout(Duration.ofMillis(5000))
                .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(5000, TimeUnit.MILLISECONDS))
                        .addHandlerLast(new WriteTimeoutHandler(5000, TimeUnit.MILLISECONDS)));
    WebClient webClient = WebClient.builder()
                    .clientConnector(new ReactorClientHttpConnector(httpClient))
                    .build();
    WebClientReactiveClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient =
                    new WebClientReactiveClientCredentialsTokenResponseClient();
            clientCredentialsTokenResponseClient.setWebClient(webClient);
    

    并添加您的 authorizedClientProvider ->

    ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder
                .builder().password(builder -> builder.accessTokenResponseClient(clientCredentialsTokenResponseClient)).build();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      • 2017-10-02
      相关资源
      最近更新 更多