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);