首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RestHighLevelClient与OAuth2的结合

RestHighLevelClient与OAuth2的结合
EN

Stack Overflow用户
提问于 2021-04-12 14:02:03
回答 1查看 179关注 0票数 2

我维护了一个高效的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配置:

代码语言:javascript
复制
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;
    }
    
}   
EN

回答 1

Stack Overflow用户

发布于 2022-01-12 17:34:05

我终于找到了一个可行的解决方案。Apache HttpRequestInterceptor可用于附加附加http标头。

代码语言:javascript
复制
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);
    }

}

然后,可以在工厂方法中注入拦截器:

代码语言:javascript
复制
    @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);
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67059825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档