Apache http 客户端自签名证书

Apache http client self signed cert

我正在尝试通过 Apache HTTP 客户端向 Web 服务发出 HTTP 请求,但我收到 javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

我按照下面的建议进行测试,但仍然遇到同样的错误。我错过了什么吗? https://memorynotfound.com/ignore-certificate-errors-apache-httpclient/

import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.*;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.*;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

public class TestHttpSSL {

    public static void main(String... args)  {

        try (CloseableHttpClient httpclient = createAcceptSelfSignedCertificateClient()) {
            HttpGet httpget = new HttpGet("https://myurl/");
            System.out.println("Executing request " + httpget.getRequestLine());

            httpclient.execute(httpget);
            System.out.println("----------------------------------------");
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException | IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static CloseableHttpClient createAcceptSelfSignedCertificateClient()
            throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

        SSLContext sslContext = SSLContextBuilder
                .create()
                .loadTrustMaterial(new TrustSelfSignedStrategy())
                .build();

        HostnameVerifier allowAllHosts = new NoopHostnameVerifier();

        SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);

        return HttpClients
                .custom()
                .setSSLSocketFactory(connectionFactory)
                .build();
    }
}

从问题中不清楚你想要达到什么。

如果您需要为“https://myurl/”使用自签名证书,您应该将此证书提供给信任库。示例(假设您已将证书放入 resources 文件夹并将其路径分配给 certPath 变量并将其密码分配给 certPassword):

KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
byte[] certificate = IOUtils.toByteArray(this.getClass().getResourceAsStream(certPath));
ByteArrayInputStream bis = new ByteArrayInputStream(certificate);
trustStore.load(bis, certPassword.toCharArray());

这里,为了简单起见,IOUtils用于将输入流转换为字节数组,但您可以手动完成。您可以选择将证书类型传递给 getInstance 方法,而不是使用默认方法 (f.e., KeyStore.getInstance("PKCS12");)

然后在创建时使用准备好的信任库 SSLContext:

SSLContext sslContext = SSLContextBuilder
        .create()
        .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
        .build();

如果您想要完全禁用 SSL 检查,则可以使用 the another strategy - TrustAllStrategy。在这种情况下,您根本不需要设置任何信任库。示例:

SSLContext sslContext = SSLContextBuilder
        .create()
        .loadTrustMaterial(null, new TrustAllStrategy())
        .build();