Apache HTTP 客户端 SSL 如何接受所有证书以进行测试
Apache HTTP Client SSL how acccept all certificates for testing purposes
我有一个 java 黄瓜测试自动化框架,我正在使用它来测试 apis。
以前我使用的是一个名为 Karate 的工具,它有一个简单的标志 (karate.configure('ssl', { trustAll: true });) 允许您信任所有证书。
我希望有一个类似的标志用于 Apache HTTP 客户端...但是我所有的谷歌搜索导致代码又长又复杂。
这是我到目前为止编写的用于将 .pfx 文件发送到 api
的代码
String keyPassphrase = "";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("src/main/resources/sslCertificates/certificate.pfx"), keyPassphrase.toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, null)
.build();
//This is the httpClient that you will use to send your http request
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
//Send the request
CloseableHttpResponse response = httpClient.execute(request);
但它在发送之前被拒绝说
"javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
我怎样才能轻松接受所有证书来解决这个问题?如前所述,我只是在测试,所以这样做没有问题。
不过我确实有 .pfx 和 .crt 格式的证书文件和一个可能被使用的 client.key 文件 - 但我不知道如何使用。
我使用了这个post中提到的解决方案:
在那里,您构建自定义 TrustManager 和 HostNameVerifier 以接受任何证书和域:
HostNameVerifier 的自定义实现:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
public class TrustAllHostNameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
创建 HTTPS 连接:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setHostnameVerifier(new TrustAllHostNameVerifier())
} catch (Exception e) {
:
:
}
虽然您澄清说它是用于测试目的,但请务必记住,这是一个极其不安全的解决方案,您会失去使用 SSL 提供的所有保护。
如果使用 HttpClient 4.4 或更高版本,您可以执行以下操作(示例取自下面的参考):
TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
BasicHttpClientConnectionManager connectionManager =
new BasicHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.setConnectionManager(connectionManager).build();
此处有更多详细信息:https://www.baeldung.com/httpclient-ssl
这段代码似乎已经成功了:
String keyPassphrase = "";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("src/main/resources/sslCertificates/certificate.pfx"), keyPassphrase.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, null);
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
//This is the httpClient that you will use to send your http request
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
//Send the request
CloseableHttpResponse response = httpClient.execute(request);
我有一个 java 黄瓜测试自动化框架,我正在使用它来测试 apis。
以前我使用的是一个名为 Karate 的工具,它有一个简单的标志 (karate.configure('ssl', { trustAll: true });) 允许您信任所有证书。
我希望有一个类似的标志用于 Apache HTTP 客户端...但是我所有的谷歌搜索导致代码又长又复杂。
这是我到目前为止编写的用于将 .pfx 文件发送到 api
的代码 String keyPassphrase = "";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("src/main/resources/sslCertificates/certificate.pfx"), keyPassphrase.toCharArray());
SSLContext sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStore, null)
.build();
//This is the httpClient that you will use to send your http request
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
//Send the request
CloseableHttpResponse response = httpClient.execute(request);
但它在发送之前被拒绝说
"javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
我怎样才能轻松接受所有证书来解决这个问题?如前所述,我只是在测试,所以这样做没有问题。
不过我确实有 .pfx 和 .crt 格式的证书文件和一个可能被使用的 client.key 文件 - 但我不知道如何使用。
我使用了这个post中提到的解决方案:
在那里,您构建自定义 TrustManager 和 HostNameVerifier 以接受任何证书和域:
HostNameVerifier 的自定义实现:
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;
public class TrustAllHostNameVerifier implements HostnameVerifier {
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
创建 HTTPS 连接:
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
try {
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection.setHostnameVerifier(new TrustAllHostNameVerifier())
} catch (Exception e) {
:
:
}
虽然您澄清说它是用于测试目的,但请务必记住,这是一个极其不安全的解决方案,您会失去使用 SSL 提供的所有保护。
如果使用 HttpClient 4.4 或更高版本,您可以执行以下操作(示例取自下面的参考):
TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,
NoopHostnameVerifier.INSTANCE);
Registry<ConnectionSocketFactory> socketFactoryRegistry =
RegistryBuilder.<ConnectionSocketFactory> create()
.register("https", sslsf)
.register("http", new PlainConnectionSocketFactory())
.build();
BasicHttpClientConnectionManager connectionManager =
new BasicHttpClientConnectionManager(socketFactoryRegistry);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
.setConnectionManager(connectionManager).build();
此处有更多详细信息:https://www.baeldung.com/httpclient-ssl
这段代码似乎已经成功了:
String keyPassphrase = "";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream("src/main/resources/sslCertificates/certificate.pfx"), keyPassphrase.toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, null);
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
//This is the httpClient that you will use to send your http request
CloseableHttpClient httpClient = HttpClients.custom().setSSLContext(sslContext).build();
//Send the request
CloseableHttpResponse response = httpClient.execute(request);