我维护了一个高效的Service (2.3.x),它使用来自RestHighLevelClient (7.10.x)的elasticsearch-rest-high-level-client (7.10.x)连接到远程弹性搜索集群。这就像一种魅力,但是现在远程服务提供商已经用OAuth2代理保护了它的服务。对于常见的REST端点来说,这是可以的,Spring提供了所需的一切:您只需将标准的Spring RestTemplate替换为来自spring-security-oauth2的OAuth2RestTemplate。它在Kibana和浏览器上也能正常工作。
但是弹性客户端是一个很难破解的难题:我无法用支持Elastic2.0的东西取代Elastic2.0的RestClient。他们的代码对交换实现是非常有抵抗力的。没有接口,没有抽象层。不过,我还是想保留Elastic的HighLevelClient,这比发送普通的JSON要方便得多。
有没有人成功地把弹性RestHighLevelClient和OAuth结合起来?是否有任何兼容的或替代的库?
下面是我目前使用的Spring配置:
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
@Configuration
public class ElasticSearchClientConfiguration {
// Elastic HighLevelClient currently used for searching, esp. msearch
@Bean
RestHighLevelClient restHighLevelClient() throws KeyManagementException, SSLException, NoSuchAlgorithmException {
return new RestHighLevelClient(createRestClientBuilder());
}
private RestClientBuilder createRestClientBuilder()
throws KeyManagementException, SSLException, NoSuchAlgorithmException {
// ... some more configs here
return RestClient.builder(new HttpHost(host, port, scheme)).setHttpClientConfigCallback(callback);
}
// Spring's OAuth2RestTemplate, used to call some other remote REST endpoints.
@Bean
public OAuth2RestTemplate oauth2RestTemplate() {
final ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setClientId(clientId);
resourceDetails.setClientSecret(loadSecret(clientSecretFileName));
resourceDetails.setScope(Collections.singletonList(resource));
resourceDetails.setAccessTokenUri(accessTokenUri);
final ClientCredentialsAccessTokenProvider tokenProvider = new ClientCredentialsAccessTokenProvider();
final OAuth2RestTemplate template = new OAuth2RestTemplate(resourceDetails);
template.setAccessTokenProvider(tokenProvider);
return template;
}
} 发布于 2022-01-12 17:34:05
我终于找到了一个可行的解决方案。Apache HttpRequestInterceptor可用于附加附加http标头。
import org.apache.http.Header;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HttpContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class OAuthInterceptor implements HttpRequestInterceptor {
private static final String HEADER_AUTHORIZATION_KEY = "Authorization";
@Autowired
private OAuthTokenProvider tokenProvider; // this service fetches the token
@Override
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
if (!(request instanceof HttpRequestWrapper)) {
throw new HttpException("Unsupported request type: " + request.getClass());
}
final HttpRequestWrapper wrapper = (HttpRequestWrapper) request;
wrapper.addHeader(createAuthorizationHeader());
}
private Header createAuthorizationHeader() {
final String auth = tokenProvider.getAuthorization();
return new BasicHeader(HEADER_AUTHORIZATION_KEY, auth);
}
}然后,可以在工厂方法中注入拦截器:
@Bean
RestHighLevelClient restHighLevelClient(OAuthInterceptor oAuthInterceptor) throws KeyManagementException, SSLException, NoSuchAlgorithmException {
final CredentialsProvider credentialsProvider = createCredentialsProvider();
final RequestConfig config = RequestConfig.custom()
.setConnectTimeout(connectTimeout)
.setConnectionRequestTimeout(connectionRequestTimeout)
.setSocketTimeout(socketTimeout)
.build();
final HttpClientConfigCallback callback = new HttpClientConfigCallback() {
@Override
public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder asyncClientBuilder) {
return asyncClientBuilder
.setDefaultCredentialsProvider(credentialsProvider)
.setDefaultRequestConfig(config)
.addInterceptorFirst(oAuthInterceptor); // That's the trick
}
};
final RestClientBuilder builder = RestClient.builder(new HttpHost(host, port, scheme)).setHttpClientConfigCallback(callback);
return new RestHighLevelClient(builder);
}https://stackoverflow.com/questions/67059825
复制相似问题