報錯sun.security.validator.ValidatorException: PKIX path building failed

在執行webservice的過程中,出現如下異常:

 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

這是缺少安全證書時出現的異常,解決方案就是將你要訪問的webservice的安全認證證書導入到客戶端即可。

以下是獲取安全證書的一種方法:

用如下程序獲取證書:

在eclipse中執行InstallCert.java文件:

/*
 * Copyright 2006 Sun Microsystems, Inc.  All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
import java.io.*;
 
import java.security.*;
import java.security.cert.*;
 
import javax.net.ssl.*;
 
public class InstallCert {
 
    public static void main(String[] args) throws Exception {
	String host;
	int port;
	char[] passphrase;
	String[] h={"litc.xforceplus.com"};//這是要訪問的webservice的網址
	if ((h.length == 1) || (h.length == 2)) {
	    String[] c = h[0].split(":");
	    host = c[0];
	    port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
	    String p = (h.length == 1) ? "changeit" : h[1];
	    passphrase = p.toCharArray();
	} else {
	    System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
	    return;
	}
 
	File file = new File("jssecacerts");
	if (file.isFile() == false) {
	    char SEP = File.separatorChar;
	    File dir = new File(System.getProperty("java.home") + SEP
		    + "lib" + SEP + "security");
	    file = new File(dir, "jssecacerts");
	    if (file.isFile() == false) {
		file = new File(dir, "cacerts");
	    }
	}
	System.out.println("Loading KeyStore " + file + "...");
	InputStream in = new FileInputStream(file);
	KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
	ks.load(in, passphrase);
	in.close();
 
	SSLContext context = SSLContext.getInstance("TLS");
	TrustManagerFactory tmf =
	    TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
	tmf.init(ks);
	X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
	SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
	context.init(null, new TrustManager[] {tm}, null);
	SSLSocketFactory factory = context.getSocketFactory();
 
	System.out.println("Opening connection to " + host + ":" + port + "...");
	SSLSocket socket = (SSLSocket)factory.createSocket(host, port);
	socket.setSoTimeout(10000);
	try {
	    System.out.println("Starting SSL handshake...");
	    socket.startHandshake();
	    socket.close();
	    System.out.println();
	    System.out.println("No errors, certificate is already trusted");
	} catch (SSLException e) {
	    System.out.println();
	    e.printStackTrace(System.out);
	}
 
	X509Certificate[] chain = tm.chain;
	if (chain == null) {
	    System.out.println("Could not obtain server certificate chain");
	    return;
	}
 
	BufferedReader reader =
		new BufferedReader(new InputStreamReader(System.in));
 
	System.out.println();
	System.out.println("Server sent " + chain.length + " certificate(s):");
	System.out.println();
	MessageDigest sha1 = MessageDigest.getInstance("SHA1");
	MessageDigest md5 = MessageDigest.getInstance("MD5");
	for (int i = 0; i < chain.length; i++) {
	    X509Certificate cert = chain[i];
	    System.out.println
	    	(" " + (i + 1) + " Subject " + cert.getSubjectDN());
	    System.out.println("   Issuer  " + cert.getIssuerDN());
	    sha1.update(cert.getEncoded());
	    System.out.println("   sha1    " + toHexString(sha1.digest()));
	    md5.update(cert.getEncoded());
	    System.out.println("   md5     " + toHexString(md5.digest()));
	    System.out.println();
	}
 
	System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
	String line = reader.readLine().trim();
	int k;
	try {
	    k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
	} catch (NumberFormatException e) {
	    System.out.println("KeyStore not changed");
	    return;
	}
 
	X509Certificate cert = chain[k];
	String alias = host + "-" + (k + 1);
	ks.setCertificateEntry(alias, cert);
 
	OutputStream out = new FileOutputStream("jssecacerts");
	ks.store(out, passphrase);
	out.close();
 
	System.out.println();
	System.out.println(cert);
	System.out.println();
	System.out.println
		("Added certificate to keystore 'jssecacerts' using alias '"
		+ alias + "'");
    }
 
    private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
 
    private static String toHexString(byte[] bytes) {
	StringBuilder sb = new StringBuilder(bytes.length * 3);
	for (int b : bytes) {
	    b &= 0xff;
	    sb.append(HEXDIGITS[b >> 4]);
	    sb.append(HEXDIGITS[b & 15]);
	    sb.append(' ');
	}
	return sb.toString();
    }
 
    private static class SavingTrustManager implements X509TrustManager {
 
	private final X509TrustManager tm;
	private X509Certificate[] chain;
 
	SavingTrustManager(X509TrustManager tm) {
	    this.tm = tm;
	}
 
	public X509Certificate[] getAcceptedIssuers() {
	    throw new UnsupportedOperationException();
	}
 
	public void checkClientTrusted(X509Certificate[] chain, String authType)
		throws CertificateException {
	    throw new UnsupportedOperationException();
	}
 
	public void checkServerTrusted(X509Certificate[] chain, String authType)
		throws CertificateException {
	    this.chain = chain;
	    tm.checkServerTrusted(chain, authType);
	}
    }
 
}

run -->Java application,控制檯輸出:

Loading KeyStore C:\Program Files\Java\jre1.8.0_152\lib\security\cacerts...
Opening connection to litc.xforceplus.com:443...
Starting SSL handshake...
 
javax.net.ssl.SSLException: java.lang.UnsupportedOperationException
	at sun.security.ssl.Alerts.getSSLException(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.handleException(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.startHandshake(Unknown Source)
	at InstallCert.main(InstallCert.java:87)
Caused by: java.lang.UnsupportedOperationException
	at InstallCert$SavingTrustManager.getAcceptedIssuers(InstallCert.java:171)
	at sun.security.ssl.AbstractTrustManagerWrapper.checkAlgorithmConstraints(Unknown Source)
	at sun.security.ssl.AbstractTrustManagerWrapper.checkAdditionalTrust(Unknown Source)
	at sun.security.ssl.AbstractTrustManagerWrapper.checkServerTrusted(Unknown Source)
	at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
	at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
	at sun.security.ssl.Handshaker.processLoop(Unknown Source)
	at sun.security.ssl.Handshaker.process_record(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
	... 3 more
 
Server sent 3 certificate(s):
 
 1 Subject CN=*.xforceplus.com, ST=上海市, L=上海市, O=上海雲礪信息科技有限公司, C=CN
   Issuer  CN=WoSign OV SSL CA, O=WoSign CA Limited, C=CN
   sha1    bb 10 54 02 19 1c fa 9b ac 08 ff 08 b4 a4 89 01 fb dd cf ed 
   md5     23 5b ad 02 60 48 12 c8 a4 63 eb 8d 8d 7e 1b be 
 
 2 Subject CN=WoSign OV SSL CA, O=WoSign CA Limited, C=CN
   Issuer  CN=Certum Trusted Network CA, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL
   sha1    fa ee 1f 69 0e dd 55 37 3c 35 e4 91 ef 05 14 f3 ee 94 45 a5 
   md5     f1 db b5 f7 4c fe 54 46 c8 a2 73 dc 3e 8a 45 ad 
 
 3 Subject CN=Certum Trusted Network CA, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL
   Issuer  CN=Certum CA, O=Unizeto Sp. z o.o., C=PL
   sha1    92 9b ad f2 60 81 52 34 90 ed c9 11 54 b3 80 a4 77 6e 21 85 
   md5     6b 83 99 12 74 59 6d 9e fe 48 82 5e 73 b7 04 40 
 
Enter certificate to add to trusted keystore or 'q' to quit: [1]

輸入1,然後直接回車,會在InstallCert.java所在項目的根目錄下生成一個名爲‘jssecacerts’的證書。

如果是服務器上,可以將‘jssecacerts’的證書放到一個目錄下/erp/test/apps/apps_st/comn/java/classes/com/zshare/,

在調用webservice接口前去加載這個證書:
 

System.setProperty("javax.net.ssl.trustStore", "/erp/test/apps/apps_st/comn/java/classes/com/zshare/jssecacerts"); 

網上看到的其他方法:

將證書copy到$JAVA_HOME/jre/lib/security目錄下,或者通過以下方式

System.setProperty("javax.net.ssl.trustStore", "D:\\UTA\\DOC_E_Health_XML\\Keystore\\jssecacerts");

注意:要重新啓動你的應用服務器,因是靜態加載,證書才能被運用上。
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章