我正在嘗試通過 SSL 將 Micrometer 與 Elasticsearch一起使用。
我在 1.8.0 版中使用 Micrometer,在 7.16.3 版和 OpenJDK 11.0.2 中使用 Elasticsearch。
因為我知道不可能使用內置配置(鏈接),所以我嘗試在以下類SecureHttpSender中注入自定義HttpUrlConnectionSender:
public class SecureHttpSender extends HttpUrlConnectionSender {
...
public SecureHttpSender(ElasticProperties properties, SecureElasticProperties secureElasticProperties) {
super(properties.getConnectTimeout(), properties.getReadTimeout());
this.secureElasticProperties = secureElasticProperties;
this.sslSocketFactory = buildSslSocketFactory();
}
@Override
public Response send(Request request) throws IOException {
HttpURLConnection httpURLConnection = null;
try {
httpURLConnection = (HttpURLConnection) request.getUrl().openConnection();
// if the connection is an instance of the HttpsURLConnection class, the ssl configuration will always been applied.
if (httpURLConnection instanceof HttpsURLConnection) {
// - hostname verifier
if (!secureElasticProperties.isVerifyHostname()) {
logger.debug("setting the hostname verifier to: {}", NoopHostnameVerifier.INSTANCE);
((HttpsURLConnection) httpURLConnection).setHostnameVerifier(NoopHostnameVerifier.INSTANCE);
}
// - trust store configuration
((HttpsURLConnection) httpURLConnection).setSSLSocketFactory(sslSocketFactory);
}
return super.send(request);
} finally {
try {
if (httpURLConnection != null) {
httpURLConnection.disconnect();
}
} catch (Exception ignore) {
}
}
}
private SSLSocketFactory buildSslSocketFactory() {
SSLSocketFactory sslSocketFactory;
try (InputStream is = getInputStream(secureElasticProperties.getTrustStorePath())) {
KeyStore truststore = KeyStore.getInstance(secureElasticProperties.getTrustStoreType());
truststore.load(is, secureElasticProperties.getTrustStorePassword().toCharArray());
SSLContextBuilder sslBuilder = SSLContexts.custom().loadTrustMaterial(truststore, null);
final SSLContext sslContext = sslBuilder.build();
sslSocketFactory = sslContext.getSocketFactory();
} catch (IOException | CertificateException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
String message = String.format("error while loading the security configuration from: %s", secureElasticProperties);
logger.error(message, e);
throw new RuntimeException("management.metrics.export.elastic.ssl");
}
return sslSocketFactory;
}
private InputStream getInputStream(String trustStorePathString) throws IOException {
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
Resource resource = pathMatchingResourcePatternResolver.getResource(trustStorePathString);
return resource.getInputStream();
}
}
我注入了 Spring Boot,以便可以應用所需的配置,但出現以下錯誤:
ERROR 10912 --- [trics-publisher] i.m.elastic.ElasticMeterRegistry : failed to send metrics to elastic
javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
服務器證書和客戶端信任庫是有效的,因為我已經成功使用了它們。我還嘗試在握手階段強制使用特定版本的 TLS 協議:TLSv1.3 和 TLSv1.2,但錯誤仍然存??在。
有人對如何修復它有任何建議嗎?謝謝
uj5u.com熱心網友回復:
檢查什么super.send,它會創建一個新連接而不使用您創建的連接。我不建議使用自簽名證書和自定義信任庫,但您可以HostnameVerifier使用
HttpsURLConnection.setDefaultHostnameVerifier.
由于這是靜態的,因此它適用于所有HttpsURLConnection實體,因此您無需向 Micrometer 注入任何東西。
正確的解決方案是使用非自簽名證書或適當的信任庫(例如: via javax.net.ssl.trustStore)。
uj5u.com熱心網友回復:
我對已發布的代碼進行了簡單更改并解決了它:我復制了super.send()方法的所有代碼,添加了附加代碼以設定自定義SslSocketFactory,一切正常!
所以原因是
它在不使用您創建的連接的情況下創建一個新連接
正如喬納坦所說......我的一個小錯誤。:)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/437232.html
