用httpclient访问https 资源时,会出现异常,与环境也有关系,有些机器请求正常.
错误详情:
- 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 com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
- at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1623)
- at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:198)
- at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:192)
- at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1074)
- at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:128)
- at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:529)
- at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:465)
- at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
- at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1120)
- at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1147)
- at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1131)
- at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
- at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
- at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1049)
- at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:234)
- at com.msd.payCenter.msdPay.yeePay.util.HttpUtils.URLGet(HttpUtils.java:67)
- at com.msd.payCenter.msdPay.yeePay.service.impl.YeePayServiceImpl.yeeAutoCheckOrder(YeePayServiceImpl.java:298)
- at com.msd.payCenter.msdPay.AutoCheckOrderServiceImpl.autoCheckOrder(AutoCheckOrderServiceImpl.java:83)
- at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
解决方法:
增加一个自己的https协议类 MySSLSocketFactory.java
- package com.nassir.hc3;
- 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.ConnectTimeoutException;
- import org.apache.commons.httpclient.params.HttpConnectionParams;
- import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
- public class MySSLSocketFactory implements ProtocolSocketFactory {
- static {
- System.out.println(">>>>in MySSLSocketFactory>>");
- }
- 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 (this.sslcontext == null) {
- 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[] {};
- }
- }
- }
请求类:
- /**
- *
- */
- package com.nassir.hc3;
- import java.io.IOException;
- import java.io.InputStream;
- import org.apache.commons.httpclient.HttpClient;
- import org.apache.commons.httpclient.HttpException;
- import org.apache.commons.httpclient.HttpMethod;
- import org.apache.commons.httpclient.methods.PostMethod;
- import org.apache.commons.httpclient.protocol.Protocol;
- /**
- * @author nassir wen
- * @data 2012-3-31 下午05:09:13
- * @version V2.5
- * @Company: MSD.
- * @Copyright Copyright (c) 2012
- */
- public class HttpsRequest {
- /**
- *
- * @param url
- * @return
- */
- public static String post(String url) {
- //增加下面两行代码
- Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
- Protocol.registerProtocol("https", myhttps);
- HttpClient client = new HttpClient();
- HttpMethod post = new PostMethod(url);
- try {
- client.executeMethod(post);
- byte[] responseBody = post.getResponseBody();
- String result = new String(responseBody,"GBK");
- return result;
- } catch (HttpException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- post.releaseConnection();
- }
- return null;
- }
- }
测试:
- public static void main(String[] args) {
- System.out.println(HttpsRequest.post("https://www.alipay.com"));//支付宝做测试
- }
解决方案来源:http://hi.baidu.com/69hwj/blog/item/3e9e457bf2f8b1f10bd18766.html
附件包含:以上代码以及httpclient3.x与httpclient4.x 事例.