`

Java的HttpClient如何去支持无证书访问https

阅读更多
项目里需要访问其他接口,通过http/https协议。我们一般是用HttpClient类来实现具体的http/https协议接口的调用。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=http://www.xxx.com/xxx;

// Init a HttpMethod
HttpMethod get = new GetMethod(url);
get.setDoAuthentication(true);
get.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(1, false));

// Call http interface
try {
    client.executeMethod(get);

    // Handle the response from http interface
    InputStream in = get.getResponseBodyAsStream();
    SAXReader reader = new SAXReader();
    Document doc = reader.read(in);
} finally {
    // Release the http connection
    get.releaseConnection();
}

以上代码在通过普通的http协议是没有问题的,但如果是https协议的话,就会有证书文件的要求了。一般情况下,是这样去做的。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=https://www.xxx.com/xxx;

if (url.startsWith("https:")) {
    System.setProperty("javax.net.ssl.trustStore", "/.sis.cer");
    System.setProperty("javax.net.ssl.trustStorePassword", "public");
}

......

于是,这里就需要事先生成一个.sis.cer的文件,生成这个文件的方法一般是先通过浏览器访问https://,导出证书文件,再用JAVA keytool command 生成证书

# $JAVA_HOME/bin/keytool -import -file sis.cer -keystore .sis.cer

但这样做,一比较麻烦,二来证书也有有效期,过了有效期之后,又需要重新生成一次证书。如果能够避开生成证书文件的方式来使用https的话,就比较好了。

还好,在最近的项目里,我们终于找到了方法。

// Init a HttpClient
HttpClient client = new HttpClient();
String url=https://www.xxx.com/xxx;

if (url.startsWith("https:")) {
    this.supportSSL(url, client);
}

......

这里用到了supportSSL(url, client)这个方法,看看这个方法是如何实现的。

private void supportSSL(String url, HttpClient client) {
        if(StringUtils.isBlank(url)) {
            return;
        }
        String siteUrl = StringUtils.lowerCase(url);
        if (!(siteUrl.startsWith("https"))) {
            return;
        }
      
        try {
            setSSLProtocol(siteUrl, client);
        } catch (Exception e) {
            logger.error("setProtocol error ", e);
        }
        Security.setProperty( "ssl.SocketFactory.provider",
        "com.tool.util.DummySSLSocketFactory");
    }

private static void setSSLProtocol(String strUrl, HttpClient client) throws Exception {
      
        URL url = new URL(strUrl);
        String host = url.getHost();
        int port = url.getPort();

        if (port <= 0) {
            port = 443;
        }
        ProtocolSocketFactory factory = new SSLSocketFactory();
        Protocol authhttps = new Protocol("https", factory, port);
        Protocol.registerProtocol("https", authhttps);
        // set https protocol
        client.getHostConfiguration().setHost(host, port, authhttps);
    }

在supportSSL方法里,调用了Security.setProperty( "ssl.SocketFactory.provider",
        "com.tool.util.DummySSLSocketFactory");

那么这个com.tool.util.DummySSLSocketFactory是这样的:



访问https 资源时,让httpclient接受所有ssl证书,在weblogic等容器中很有用
代码如下:


Java代码

   1. import java.io.IOException; 
   2. import java.net.InetAddress; 
   3. import java.net.InetSocketAddress; 
   4. import java.net.Socket; 
   5. import java.net.SocketAddress; 
   6. import java.net.UnknownHostException; 
   7. import java.security.KeyManagementException; 
   8. import java.security.NoSuchAlgorithmException; 
   9. import java.security.cert.CertificateException; 
  10. import java.security.cert.X509Certificate; 
  11.  
  12. import javax.net.SocketFactory; 
  13. import javax.net.ssl.SSLContext; 
  14. import javax.net.ssl.TrustManager; 
  15. import javax.net.ssl.X509TrustManager; 
  16.  
  17. import org.apache.commons.httpclient.ConnectTimeoutException; 
  18. import org.apache.commons.httpclient.params.HttpConnectionParams; 
  19. import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory; 
  20.  
  21. public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory { 
  22.     static{ 
  23.         System.out.println(">>>>in MySecureProtocolSocketFactory>>"); 
  24.     } 
  25.     private SSLContext sslcontext = null; 
  26.     
  27.     private SSLContext createSSLContext() { 
  28.         SSLContext sslcontext=null; 
  29.         try { 
  30.             sslcontext = SSLContext.getInstance("SSL"); 
  31.             sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, new java.security.SecureRandom()); 
  32.         } catch (NoSuchAlgorithmException e) { 
  33.             e.printStackTrace(); 
  34.         } catch (KeyManagementException e) { 
  35.             e.printStackTrace(); 
  36.         } 
  37.         return sslcontext; 
  38.     } 
  39.     
  40.     private SSLContext getSSLContext() { 
  41.         if (this.sslcontext == null) { 
  42.             this.sslcontext = createSSLContext(); 
  43.         } 
  44.         return this.sslcontext; 
  45.     } 
  46.     
  47.     public Socket createSocket(Socket socket, String host, int port, boolean autoClose) 
  48.             throws IOException, UnknownHostException { 
  49.         return getSSLContext().getSocketFactory().createSocket( 
  50.                 socket, 
  51.                 host, 
  52.                 port, 
  53.                 autoClose 
  54.             ); 
  55.     } 
  56.  
  57.     public Socket createSocket(String host, int port) throws IOException, 
  58.             UnknownHostException { 
  59.         return getSSLContext().getSocketFactory().createSocket( 
  60.                 host, 
  61.                 port 
  62.             ); 
  63.     } 
  64.     
  65.     
  66.     public Socket createSocket(String host, int port, InetAddress clientHost, int clientPort) 
  67.             throws IOException, UnknownHostException { 
  68.         return getSSLContext().getSocketFactory().createSocket(host, port, clientHost, clientPort); 
  69.     } 
  70.  
  71.     public Socket createSocket(String host, int port, InetAddress localAddress, 
  72.             int localPort, HttpConnectionParams params) throws IOException, 
  73.             UnknownHostException, ConnectTimeoutException { 
  74.         if (params == null) { 
  75.             throw new IllegalArgumentException("Parameters may not be null"); 
  76.         } 
  77.         int timeout = params.getConnectionTimeout(); 
  78.         SocketFactory socketfactory = getSSLContext().getSocketFactory(); 
  79.         if (timeout == 0) { 
  80.             return socketfactory.createSocket(host, port, localAddress, localPort); 
  81.         } else { 
  82.             Socket socket = socketfactory.createSocket(); 
  83.             SocketAddress localaddr = new InetSocketAddress(localAddress, localPort); 
  84.             SocketAddress remoteaddr = new InetSocketAddress(host, port); 
  85.             socket.bind(localaddr); 
  86.             socket.connect(remoteaddr, timeout); 
  87.             return socket; 
  88.         } 
  89.     } 
  90.     
  91.     //自定义私有类 
  92.     private static class TrustAnyTrustManager implements X509TrustManager { 
  93.        
  94.         public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
  95.         } 
  96.    
  97.         public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { 
  98.         } 
  99.    
100.         public X509Certificate[] getAcceptedIssuers() { 
101.             return new X509Certificate[]{}; 
102.         } 
103.     }    
104.  
105. } 

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.SecureProtocolSocketFactory;

public class MySecureProtocolSocketFactory implements SecureProtocolSocketFactory {
    static{
        System.out.println(">>>>in MySecureProtocolSocketFactory>>");
    }
    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[]{};
        }
    }  

}



然后按如下方式使用HttpClient

Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
Protocol.registerProtocol("https", myhttps);
HttpClient httpclient=new HttpClient();
之后就是照常使用了,不知道怎样用的话,参考我的其它文章
分享到:
评论
1 楼 alosin 2011-03-18  
那httpclient 4 已经取消了protocol,该怎么办呢,研究了很久,网上的资料都不行

相关推荐

Global site tag (gtag.js) - Google Analytics