我收到一个http 403 forbidden
错误,试图通过Java Jest(v6.3) elasticsearch客户端(将http调用委托给apache httpclient(v4.5.2)的客户端)删除aws elasticsearch
索引,我知道在AWS上正确设置了权限,因为我能够成功使用邮递员(借助AWS Signature授权帮助器)。但是,在使用apache httpclient
时,当我发出DELETE /{myIndexName}
时,收到以下错误:
The request signature we calculated does not match the signature you provided.
Check your AWS Secret Access Key and signing method.
Consult the service documentation for details.
我正在通过为aws
配置一个带有签署请求的拦截器来签署apache httpclient
请求。(下面的代码适用于Spring Framework @Configuration
类,它将Java {{ 1}}客户和底层的Apache httpclient),但我想如果我直接使用apache httpclient也会遇到同样的问题。
Jest
由于它与邮递员一起工作,因此它指向一个签名错误,但是我对出现差异的地方不知所措。上面的配置适用于除http DELETE请求之外的所有@Configuration
public class ElasticSearchConfiguration {
@Autowired
private CredentialsProviderFactoryBean awsCredentialsProvider;
@Bean
public JestClient awsJestClient(@Value("${elasticsearch.url}") String connectionUrl) throws Exception {
com.amazonaws.auth.AWSCredentialsProvider provider = awsCredentialsProvider.getObject();
final com.google.common.base.Supplier<LocalDateTime> clock = () -> LocalDateTime.now(ZoneOffset.UTC);
final vc.inreach.aws.request.AWSSigner awsSigner = new vc.inreach.aws.request.AWSSigner(provider, "us-east-1", "es", clock);
final vc.inreach.aws.request.AWSSigningRequestInterceptor requestInterceptor = new vc.inreach.aws.request.AWSSigningRequestInterceptor(awsSigner);
final JestClientFactory factory = new JestClientFactory() {
@Override
protected HttpClientBuilder configureHttpClient(HttpClientBuilder builder) {
builder.addInterceptorLast(requestInterceptor);
return builder;
}
@Override
protected HttpAsyncClientBuilder configureHttpClient(HttpAsyncClientBuilder builder) {
builder.addInterceptorLast(requestInterceptor);
return builder;
}
};
factory.setHttpClientConfig(new HttpClientConfig
.Builder(connectionUrl)
.connTimeout(60000)
.multiThreaded(true)
.build());
return factory.getObject();
}
}
请求。
答案 0 :(得分:1)
经过一堆研究,我发现了一些线索,这些线索指出了向aws发出的请求中Content-Length
(长度= 0)的存在导致签名不匹配的可能性。我猜想通过客户端拦截器完成的签名未考虑到Content-Length
头中,但是由于我们将Content-Length
头发送到了aws服务器,因此将其考虑在内,从而导致签名不匹配。我相信是这样,因为我在AWS Signing拦截器之前添加了一个额外的拦截器,该拦截器显式删除了Content-Length
请求的DELETE
头,并且请求成功通过。 (即我可以删除索引)。下面更新了代码:
@Configuration
public class ElasticSearchConfiguration {
private static final Logger log = LoggerFactory.getLogger(ElasticSearchConfiguration.class);
@Autowired
private CredentialsProviderFactoryBean awsCredentialsProvider;
@Bean
public JestClient awsJestClient(@Value("${elasticsearch.url}") String connectionUrl) throws Exception {
com.amazonaws.auth.AWSCredentialsProvider provider = awsCredentialsProvider.getObject();
final com.google.common.base.Supplier<LocalDateTime> clock = () -> LocalDateTime.now(ZoneOffset.UTC);
final vc.inreach.aws.request.AWSSigner awsSigner = new vc.inreach.aws.request.AWSSigner(provider, "us-east-1", "es", clock);
final vc.inreach.aws.request.AWSSigningRequestInterceptor requestInterceptor = new vc.inreach.aws.request.AWSSigningRequestInterceptor(awsSigner);
final HttpRequestInterceptor removeDeleteMethodContentLengthHeaderRequestInterceptor = (request, context) -> {
if(request.getRequestLine().getMethod().equals("DELETE")) {
log.warn("intercepted aws es DELETE request, will remove 'Content-Length' header as it's presence invalidates the signature check on AWS' end");
request.removeHeaders("Content-Length");
}
};
final JestClientFactory factory = new JestClientFactory() {
@Override
protected HttpClientBuilder configureHttpClient(HttpClientBuilder builder) {
builder.addInterceptorLast(removeDeleteMethodContentLengthHeaderRequestInterceptor);
builder.addInterceptorLast(requestInterceptor);
return builder;
}
@Override
protected HttpAsyncClientBuilder configureHttpClient(HttpAsyncClientBuilder builder) {
builder.addInterceptorLast(removeDeleteMethodContentLengthHeaderRequestInterceptor);
builder.addInterceptorLast(requestInterceptor);
return builder;
}
};
factory.setHttpClientConfig(new HttpClientConfig
.Builder(connectionUrl)
.connTimeout(60000)
.multiThreaded(true)
.build());
return factory.getObject();
}
}