Java SOAP-PKIX路径生成失败

Java SOAP-PKIX路径生成失败,java,soap,pkcs#12,Java,Soap,Pkcs#12,我正在构建一个必须调用两个Web服务的服务器。Web服务具有相同的CA证书(PKCS12) 第一个通过GET接收请求,另一个通过SOAP调用 遵循为GET请求创建连接的部分代码 InputStream inputStream = null; // is https protocol? if (url.getProtocol().toLowerCase().equals("https")) {

我正在构建一个必须调用两个Web服务的服务器。Web服务具有相同的CA证书(PKCS12)

第一个通过GET接收请求,另一个通过SOAP调用

遵循为GET请求创建连接的部分代码

            InputStream inputStream = null;

            // is https protocol?
            if (url.getProtocol().toLowerCase().equals("https")) {

                trustAllHosts();
                // create connection
                HttpsURLConnection httpsUrlConnection = null;
                if(proxy != null){
                    httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
                } else {
                    httpsUrlConnection = (HttpsURLConnection) url.openConnection();
                }
                // set the check to: do not verify
                httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });

                setHeaders(httpsUrlConnection, headers);    

                //set del certificato

                log.debug("set certificate for get...");
                File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
                ((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd"))); 
                httpsUrlConnection.connect();

                inputStream = httpsUrlConnection.getInputStream();

            } else {
                HttpURLConnection httpUrlConnection = null;
                if(proxy != null){
                    httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
                } else {
                    httpUrlConnection = (HttpURLConnection) url.openConnection();
                }

                setHeaders(httpUrlConnection, headers);    

                inputStream = httpUrlConnection.getInputStream();
            }

            in = new BufferedReader(new InputStreamReader(inputStream));

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                result.append(inputLine);
            }
这部分用于SOAP请求

            InputStream inputStream = null;

            // is https protocol?
            if (url.getProtocol().toLowerCase().equals("https")) {

                trustAllHosts();
                // create connection
                HttpsURLConnection httpsUrlConnection = null;
                if(proxy != null){
                    httpsUrlConnection = (HttpsURLConnection) url.openConnection(proxy);
                } else {
                    httpsUrlConnection = (HttpsURLConnection) url.openConnection();
                }
                // set the check to: do not verify
                httpsUrlConnection.setHostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });

                setHeaders(httpsUrlConnection, headers);    

                //set del certificato

                log.debug("set certificate for get...");
                File cerp12 = new File(Utils.getWebAppLocalPath(),"WEB-INF"+String.valueOf(File.separatorChar)+PropConfig.getProperty("cer.p12"));
                ((HttpsURLConnection) httpsUrlConnection).setSSLSocketFactory(security(cerp12,PropConfig.getProperty("cer.pwd"))); 
                httpsUrlConnection.connect();

                inputStream = httpsUrlConnection.getInputStream();

            } else {
                HttpURLConnection httpUrlConnection = null;
                if(proxy != null){
                    httpUrlConnection = (HttpURLConnection) url.openConnection(proxy);
                } else {
                    httpUrlConnection = (HttpURLConnection) url.openConnection();
                }

                setHeaders(httpUrlConnection, headers);    

                inputStream = httpUrlConnection.getInputStream();
            }

            in = new BufferedReader(new InputStreamReader(inputStream));

            String inputLine;
            while ((inputLine = in.readLine()) != null) {
                result.append(inputLine);
            }
代码几乎相同

对于GET请求,我没有问题,但是对于SOAP请求
httpsUrlConnection.connect()抛出

PKIX路径生成失败:sun.security.provider.certpath.SunCertPathBuilderException:找不到请求目标的有效证书路径

以下是如何为HTTPS连接创建ssl上下文

        SSLSocketFactory socketFactory = createSSLContext().getSocketFactory();

        HttpsURLConnection connection = (HttpsURLConnection) (url).openConnection();
        connection.setSSLSocketFactory(socketFactory);
和方法来创建SSL上下文。注意,它从.pem文件(x509格式)加载根服务器证书,从.p12(pkcs12格式)加载客户端证书。若服务器不需要客户端证书,请为密钥管理器传递null。如果由授权机构颁发的服务器证书(已在$JRE_HOME/lib/security/cacerts中)作为信任管理器传递null

还有一点需要注意:在.pem文件中,您应该将根证书存储在服务器证书的PKIX路径中。例如,github.com该站点具有PKIX路径
CN=github.com
->
CN=DigiCert高保证EV CA-1
->
CN=DigiCert高保证EV根CA
->
CN=GTE CyberTrust全局根。因此,您存储了GTE CyberTrust Global Root

private final SSLContext createSSLContext()
            throws NoSuchAlgorithmException, KeyStoreException,
            CertificateException, IOException,
            UnrecoverableKeyException, KeyManagementException {


        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(new File(Config.getString(Config.KEYSTORE_PATH)));
        } catch (Exception ex) {
            throw new IOException("not found keystore file: " Config.getString(Config.KEYSTORE_PATH), ex);
        }
        try{
            keyStore.load(fis, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());
        }finally {
            IOUtils.closeQuietly(fis);
        }
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        FileInputStream in = new FileInputStream(Config.getString(Config.HTTPS_SERVER_CERT));
        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(null);
        try {
            X509Certificate cacert = (X509Certificate) cf.generateCertificate(in);
            trustStore.setCertificateEntry("alias", cacert);
        } finally {
            IOUtils.closeQuietly(in);
        }

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(trustStore);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(keyStore, Config.getString(Config.KEYSTORE_PASSWORD).toCharArray());

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
        return sslContext;
    }

感谢您的回复,只有一件事:什么是
Config.KEYSTORE\u PATH
<代码>p12路径还是密钥库路径?还有,我的配置中的
Config.HTTPS\u SERVER\u CERT
?Config.getString(Config.KEYSTORE\u PATH)-属性是什么。在您的例子中,它是
PropConfig.getProperty(“cer.p12”)
。HTTPS\u SERVER\u CERT-服务器certifiacte.IOUtils.closequilly的路径(in);从apache utils,您只需关闭FileInputStreamIs
HTTPS\u SERVER\u CERT
$JAVA\u HOME\jre\lib\security\cacerts?不,它只是x509格式的证书(只有一个证书),通常它有扩展名.cer、.crt、.pem。任何浏览器都可以以该格式导出证书。但是
$JAVA\u HOME\jre\lib\security\cacerts
是密钥库,可以包含多个证书。通常它包含所有根CA证书。它默认在JVM启动时加载。有时服务器使用https自签名证书,java不知道颁发证书的CA是谁,也不连接到该服务器。在这种情况下,您应该将服务url粘贴到浏览器,获取证书并将其存储为.pem文件。