如何使用Java在https连接请求中附加.pfx证书?

如何使用Java在https连接请求中附加.pfx证书?,java,ssl,https,client-certificates,sslhandshakeexception,Java,Ssl,Https,Client Certificates,Sslhandshakeexception,我有一个安装在Windows证书存储中的pfx证书,我可以使用C#在https rest调用中附加该证书 现在我需要用Java做同样的事情。我读到了。pfx证书有私钥和一个或多个证书 我收到以下错误:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径。 我在Java中尝试过的东西 我使用KeyStore ks=KeyStore.getInstance(“Windows MY”、

我有一个安装在Windows证书存储中的pfx证书,我可以使用C#在https rest调用中附加该证书

现在我需要用Java做同样的事情。我读到了。pfx证书有私钥和一个或多个证书


我收到以下错误:PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径。

我在Java中尝试过的东西

  • 我使用KeyStore ks=KeyStore.getInstance(“Windows MY”、“SunMSCAPI”)直接从Windows应用商店获取证书,并创建了一个SSLContext,用于HTTPS调用

  • 我从Windows应用商店将证书作为.cer文件导入,并从代码中将其作为文件读取,然后将其附加到https调用

  • 我从代码中读取.pfx文件并将其附加到调用中

  • 我已经使用KeyTool将证书添加到Java Home的cacerts文件(C:/Work/certi/jre1.8.0_91/lib/security/cacerts)

  • 完整的Java代码如下所示

    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.net.URLConnection;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.PrivateKey;
    import java.security.SecureRandom;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    import java.util.Enumeration;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    
    import javax.net.ssl.TrustManagerFactory;
    
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    
    
    public class TestElk {
    
    public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
            
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Certificate certificate = certificateFactory.generateCertificate(new FileInputStream(new File("C:/Work/certi/jre1.8.0_91/lib/security/elkcert.cer")));//exported certificate
    
        /* KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
        ks.load(null,null);
        
        Enumeration enumeration = ks.aliases();     
        while(enumeration.hasMoreElements()) {            
            String alias = (String)enumeration.nextElement();
            System.out.println("alias name: " + alias);        }
        
        Certificate[] certificate = ks.getCertificateChain("alias");
         */
        
        // Create TrustStore        
        KeyStore trustStoreContainingTheCertificate =     KeyStore.getInstance(KeyStore.getDefaultType());
        trustStoreContainingTheCertificate.load(null, null);
    
        trustStoreContainingTheCertificate.setCertificateEntry("cert", certificate);
    
        // Create SSLContext
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStoreContainingTheCertificate);
    
    
        final SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null,trustManagerFactory.getTrustManagers(),new SecureRandom());
        SSLContext.setDefault(sslContext);
        
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;   
        
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
    
        URL url = new URL("https://server-link");
        
        HttpsURLConnection con =    (HttpsURLConnection)url.openConnection();           
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
        con.setConnectTimeout(10000);
        con.setSSLSocketFactory(sslContext.getSocketFactory()); 
        con.connect();
        
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line+"\n");
        }
        br.close();
        System.out.println(sb.toString());
        //int s= con.getResponseCode();  }
    

    鉴于您已将颁发CA证书(请参阅下面的注释)导入到cacerts文件,以下操作应该可以正常工作,在不同的SO线程中可以找到许多帮助:


    “找不到请求目标的有效证书路径”表示根/子CA不受信任。在您的情况下,您不信任为目标“CN=*.dvb.corpinter.net”颁发服务器证书的根目录(MBIS CA)…请根据您的问题更新日志,我无法访问C:驱动器上的链接:)仅添加错误部分。。。。我会发起聊天,但我的声誉还不够,如果“CN=MBIIS CA,OU=MBIIS,O=DAIMLER,C=CN”是“CN=MBIIS CA,OU=MBIIS,O=DAIMLER,C=DE”的子类别,那么您的客户端密钥库需要提供整个链。。。当您从internet explorer导出pfx时,如果我没有弄错的话,您可以包含该链,请查看我在邮件中使用的actual.pfx证书,该证书是我在我们的程序中从clientstore创建keymanager时获得的。它只有一个证书。然后从浏览器中,我可以仅使用前3个选项进行导出。。i、 e.pfx导出已禁用:(.我们如何知道证书是否是另一个证书的子CA,然后如何添加并一起交付。
    import java.io.BufferedReader;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.NoSuchProviderException;
    import java.security.SecureRandom;
    import java.security.UnrecoverableKeyException;
    import java.security.cert.CertificateException;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.KeyManager;
    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    
    
    public class TestElk {
    
    public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
    
        
        KeyStore clientStore = KeyStore.getInstance("PKCS12");
        clientStore.load(new FileInputStream(new File("C:/path_to_pfx/mypfx.pfx")), "pfxPass".toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(clientStore, "pfxPass".toCharArray());
        KeyManager[] kms = kmf.getKeyManagers();
        
        // Assuming that you imported the CA Cert "Subject: CN=MBIIS CA, OU=MBIIS, O=DAIMLER, C=DE"
        // to your cacerts Store.
        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray());
    
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(trustStore);
        TrustManager[] tms = tmf.getTrustManagers();
    
        final SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kms,tms,new SecureRandom());
        SSLContext.setDefault(sslContext);
    
        HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;   
        System.setProperty("https.proxyHost", "IP_OF_PROXY_HOST_GOES_HERE");
        System.setProperty("https.proxyPort", "PORT_NUMBER_GOES_HERE");
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
    
        URL url = new URL("https://server-link");
    
        HttpsURLConnection con =    (HttpsURLConnection)url.openConnection();           
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
        con.setConnectTimeout(10000);
        con.setSSLSocketFactory(sslContext.getSocketFactory()); 
        con.connect();
    
        BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = br.readLine()) != null) {
            sb.append(line+"\n");
        }
        br.close();
        System.out.println(sb.toString());
        //int s= con.getResponseCode();
    }
    
    }