javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building f

这么说吧,这个问题真是日了狗了,整了两天才在大家的帮助下解决,虽然深层次的原理还不是很理解,也许不是对所有的这个情况都有用,但是解决方法还是要粘出来希望对其他人有所帮助。

问题描述:首先我有一个webservice既做服务端又做客户端,主要用作接收外部系统的请求,然后请求第三方接口,并把结果处理完成推送给请求方。我自己用客户端模拟发送请求,webservice没有任何问题正常请求第三方接口并返回数据,但是别的系统请求我的webservice,server在调用第三方接口时就会抛出这个异常。令我很费劲,实在不明白二者有什么区别,但很明显与第三方接口的服务端应该没有关系。
叙述有点绕,还是看异常吧。

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
        at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1904)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:279)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:273)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1446)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:209)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:901)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:837)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1023)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1332)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1359)
        at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1343)
        at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:563)
        at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
        at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1092)
        at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:250)
        at com.rong360.api.Rong360DataUtils.excutePost(Rong360DataUtils.java:442)
        at com.rong360.api.Rong360DataUtils.dataHandlr(Rong360DataUtils.java:82)
        at com.glorycube.msgrep.businesshandle.R006Handler.txHandleRequest(R006Handler.java:38)
        at com.ws.WsServerHandleDelegate.getMessage(WsServerHandleDelegate.java:93)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at com.sun.xml.ws.api.server.InstanceResolver$1.invoke(InstanceResolver.java:250)
        at com.sun.xml.ws.server.InvokerTube$2.invoke(InvokerTube.java:149)
        at com.sun.xml.ws.server.sei.SEIInvokerTube.processRequest(SEIInvokerTube.java:94)
        at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:961)
        at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:910)
        at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:873)
        at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:775)
        at com.sun.xml.ws.server.WSEndpointImpl$2.process(WSEndpointImpl.java:386)
        at com.sun.xml.ws.transport.http.HttpAdapter$HttpToolkit.handle(HttpAdapter.java:640)
        at com.sun.xml.ws.transport.http.HttpAdapter.handle(HttpAdapter.java:263)
        at com.sun.xml.ws.transport.http.servlet.ServletAdapter.invokeAsync(ServletAdapter.java:218)
        at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doGet(WSServletDelegate.java:159)
        at com.sun.xml.ws.transport.http.servlet.WSServletDelegate.doPost(WSServletDelegate.java:194)
        at com.sun.xml.ws.transport.http.servlet.WSServlet.doPost(WSServlet.java:80)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:650)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:218)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:169)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:442)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1082)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:623)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1428)
        ... 55 more

主要原因就是由于访问https的接口,然后会去找安全证书,解决方法如下:
第一步导入安全证书,虽然第三方公司声明不用安全证书,但是由于ssl协议会去找,这个证书最好还是加上。
1、从chrome浏览器中导出 证书的cer格式文件;
这里写图片描述
这里写图片描述
这里写图片描述
第二步:将上面导出的证书导入java中的cacerts证书库
1.查看java目录 which java
/usr/lib/jvm/java7/bin/java
2.查看证书库
keytool -list -keystore /usr/lib/jvm/java7/jre/lib/security/cacerts
此时命令行会提示你输入cacerts证书库密码,
java中cacerts证书库默认密码为changeit,
3.导入证书
keytool -import -alias LL1 -keystore /usr/lib/jvm/java7/jre/lib/security/cacerts -file /hc1/bak/tianji.cer
此时命令行会提示你输入cacerts证书库密码,
java中cacerts证书库默认密码为changeit,然后输入Y确认即可,OK,认证已添加至keystore。
4.可以再次查看证书库,此时已经总数已经多了一个,添加成功。

第三步修改发送请求的代码

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.apache.http.conn.ConnectTimeoutException;


/** 
 * httpclient https 
 * 
 */  
public class HTTPSSecureProtocolSocketFactory implements ProtocolSocketFactory {//SecureProtocolSocketFactory  
    private SSLContext sslcontext = null;  

    private SSLContext createSSLContext() {  
        SSLContext sslcontext = null;  
        try {  
            sslcontext = SSLContext.getInstance("SSL");  
            sslcontext.init(null,  
                    new TrustManager[] { new TrustAnyTrustManager() },  
                    new java.security.SecureRandom());  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        } catch (KeyManagementException e) {  
            e.printStackTrace();  
        }  
        return sslcontext;  
    }  

    private SSLContext getSSLContext() {  
        if (null == this.sslcontext) {  
            this.sslcontext = createSSLContext();  
        }  
        return this.sslcontext;  
    }  

    public Socket createSocket(Socket socket, String host, int port,  
            boolean autoClose) throws IOException, UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(socket, host,  
                port, autoClose);  
    }  

    public Socket createSocket(String host, int port) throws IOException,  
            UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(host, port);  
    }  

    public Socket createSocket(String host, int port, InetAddress clientHost,  
            int clientPort) throws IOException, UnknownHostException {  
        return getSSLContext().getSocketFactory().createSocket(host, port,  
                clientHost, clientPort);  
    }  

    public Socket createSocket(String host, int port, InetAddress localAddress,  
            int localPort, HttpConnectionParams params) throws IOException,  
            UnknownHostException, ConnectTimeoutException {  
        if (params == null) {  
            throw new IllegalArgumentException("Parameters may not be null");  
        }  
        int timeout = params.getConnectionTimeout();  
        SocketFactory socketfactory = getSSLContext().getSocketFactory();  
        if (timeout == 0) {  
            return socketfactory.createSocket(host, port, localAddress,  
                    localPort);  
        } else {  
            Socket socket = socketfactory.createSocket();  
            SocketAddress localaddr = new InetSocketAddress(localAddress,  
                    localPort);  
            SocketAddress remoteaddr = new InetSocketAddress(host, port);  
            socket.bind(localaddr);  
            socket.connect(remoteaddr, timeout);  
            return socket;  
        }  
    }  

    private static class TrustAnyTrustManager implements X509TrustManager {  
        public void checkClientTrusted(X509Certificate[] chain, String authType)  
                throws CertificateException {  
        }  

        public void checkServerTrusted(X509Certificate[] chain, String authType)  
                throws CertificateException {  
        }  

        public X509Certificate[] getAcceptedIssuers() {  
            return new X509Certificate[] {};  
        }  
    }  

}

    public static String postByHttps(String url, String body, String contentType) {
        String result = "";
        Protocol https = new Protocol("https", new HTTPSSecureProtocolSocketFactory(), 443);
        Protocol.registerProtocol("https", https);
        PostMethod post = new PostMethod(url);
        HttpClient client = new HttpClient();
        try {
            post.setRequestHeader("Content-Type", contentType);
            post.setRequestBody(body);
            client.executeMethod(post);
            result = post.getResponseBodyAsString();
            Protocol.unregisterProtocol("https");
            return result;
        } catch (HttpException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch(Exception e) {
            e.printStackTrace();
        }

        return "error";
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值