简体   繁体   English

Spring Boot WebClient 与 OAuth2 并使用 InsecureTrustManagerFactory

[英]Spring Boot WebClient with OAuth2 and use InsecureTrustManagerFactory

I have successfully implemented WebClient with oAuth2.我已经成功地使用 oAuth2 实现了 WebClient。 Facing problem with oAuth2 when the Authentication Server (Keycloak) is having SSL (https).当身份验证服务器 (Keycloak) 具有 SSL (https) 时,会遇到 oAuth2 问题。 Though I am passing InsecureTrustManagerFactory while defining WebClient, this oAuth is called before the builder is complete as it is there in the filter, it uses default implementation of WebClient and throws certification error.尽管我在定义 WebClient 时传递了 InsecureTrustManagerFactory,但在构建器完成之前调用了此 oAuth,因为它位于过滤器中,它使用 WebClient 的默认实现并引发认证错误。

Is there a way we can configure oAuth2 client also to use InsecureTrustManagerFactory?有没有办法我们可以配置 oAuth2 客户端也使用 InsecureTrustManagerFactory?

pom.xml part 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 Configuration 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();
}

So you have to make new WebClient for OAuth2 too.所以你也必须为 OAuth2 创建新的 WebClient。 In your authorizedClientManager definition add some strings(It's better to have HttpClient bean, so you won't define it all the time)在您的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);

and add in your authorizedClientProvider ->并添加您的authorizedClientProvider ->

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM