我必须迁移现有的 OAuth2RestTemplate
基于oauth2微服务的spring security/ WebClient
因为 OAuth2RestTemplate
不推荐使用。但是,新的实现无法通过代理服务器访问oauth2服务器。我已经阅读了关于这个主题的各种文章,包括spring webclient没有为最新版本的spring-security-oauth2-client-5.3.4.release使用代理,并尝试将这些文章中描述的逻辑包括在我的实现中。不幸的是没有成功。我的实现配置了底层 ClientHttpConnector
被使用 WebClient
使用适当的代理设置。请参阅下面的代码片段 WebClientConfig
(完整的代码库包括 WebClientConfig
单元测试可以在这里找到:github):
@Bean
public ReactiveClientRegistrationRepository clientRegistrationRepository() {
ClientRegistration clientRegistration = ClientRegistration
.withRegistrationId(REGISTRATION_ID)
.authorizationGrantType(AuthorizationGrantType.PASSWORD)
.clientId(CLIENT_ID)
.clientSecret(CLIENT_SECRET)
.clientAuthenticationMethod(ClientAuthenticationMethod.POST)
.userInfoAuthenticationMethod(AuthenticationMethod.FORM)
.tokenUri(restServiceProperties.getOauth2Url())
.build();
return new InMemoryReactiveClientRegistrationRepository(clientRegistration);
}
@Bean
public ReactiveOAuth2AuthorizedClientService authorizedClientService(ReactiveClientRegistrationRepository clientRegistrationRepository) {
return new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository);
}
@Bean
public ClientHttpConnector clientHttpConnector() {
HttpAsyncClientBuilder clientBuilder = HttpAsyncClients.custom();
if (Strings.isNotEmpty(restServiceProperties.getProxyUrl())) {
try {
HttpHost proxy = HttpHost.create(restServiceProperties.getProxyUrl());
clientBuilder.setRoutePlanner(new DefaultProxyRoutePlanner(proxy));
} catch (URISyntaxException e) {
log.error("Error: {}", e.getMessage());
throw new RuntimeException(e);
}
}
CloseableHttpAsyncClient client = clientBuilder.build();
return new HttpComponentsClientHttpConnector(client);
}
@Bean
public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService authorizedClientService, ClientHttpConnector clientHttpConnector, WebClient.Builder webClientBuilder) {
WebClient webClient = webClientBuilder
.clientConnector(clientHttpConnector)
.filter(logRequest())
.build();
AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(createAuthorizedClientProvider(webClient));
authorizedClientManager.setContextAttributesMapper(request -> {
Map<String, Object> contextAttributes = new HashMap<>();
contextAttributes.put(OAuth2AuthorizationContext.USERNAME_ATTRIBUTE_NAME, USER);
contextAttributes.put(OAuth2AuthorizationContext.PASSWORD_ATTRIBUTE_NAME, PASSWORD);
return Mono.just(contextAttributes);
});
return authorizedClientManager;
}
@Bean
public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager,
ClientHttpConnector clientHttpConnector, WebClient.Builder webClientBuilder) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2FilterFunction = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oauth2FilterFunction.setDefaultClientRegistrationId(REGISTRATION_ID);
return webClientBuilder
.clientConnector(clientHttpConnector)
.filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(oauth2FilterFunction);
exchangeFilterFunctions.add(logRequest());
})
.build();
}
private ReactiveOAuth2AuthorizedClientProvider createAuthorizedClientProvider(WebClient webClient) {
WebClientReactiveClientCredentialsTokenResponseClient clientCredentialsTokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();
clientCredentialsTokenResponseClient.setWebClient(webClient);
return ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials(builder -> builder.accessTokenResponseClient(clientCredentialsTokenResponseClient))
.password()
.refreshToken()
.build();
}
private ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: method: {} URL: {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach((name, values) -> values.forEach(value -> log.info("Request header: name: {} value: {}", name, value)));
return Mono.just(clientRequest);
});
}
我也试过了 clientBuilder.setProxy(proxy)
而不是 clientBuilder.setRoutePlanner(new DefaultProxyRoutePlanner(proxy))
,但这并没有解决问题。
关于单元测试: NoProxyServerTest
显示在未配置代理服务器时可以访问oauth2服务器和下游服务器。 ProxyServerTest
显示在配置代理服务器时无法访问oauth2服务器。 DirectProxyServerInvocationTest
表明 MockProxyServer
它实际上在工作。及 DownstreamServerProxyServerInvocationTest
显示可以通过代理服务器访问下游服务器。 WebClient
在中配置 WebClientConfig
. 这可能是迄今为止最好的配置,但我尝试了许多不同的配置来解决这个代理服务器问题(包括使用 https.proxyPort
, https.proxyHost
, http.proxyPort
及 http.proxyHost
).
正在使用类似的测试来测试不推荐使用的oauth2resttemplate实现。所有四个测试都通过了该实现。
暂无答案!
目前还没有任何答案,快来回答吧!