Android平台实现https信任所有证书的方法

http://blog.csdn.net/123bobo/article/details/7264350/

Android平台上经常有使用https的需求,对于https服务器使用的根证书是受信任的证书的话,实现https是非常简单的,直接用httpclient库就行了,与使用http几乎没有区别。但是在大多数情况下,服务器所使用的根证书是自签名的,或者签名机构不在设备的信任证书列表中,这样使用httpclient进行https连接就会失败。解决这个问题的办法有两种,一是在发起https连接之前将服务器证书加到httpclient的信任证书列表中,这个相对来说比较复杂一些,很容易出错;另一种办法是让httpclient信任所有的服务器证书,这种办法相对来说简单很多,但安全性则差一些,但在某些场合下有一定的应用场景。这里要举例说明的就是后一种方法:实例化HttpClinet对象时要进行一些处理主要是绑定https连接所使用的端口号,这里绑定了443和8443:

    SchemeRegistry schemeRegistry = new SchemeRegistry();  
    schemeRegistry.register(new Scheme("https",  
                        new EasySSLSocketFactory(), 443));  
    schemeRegistry.register(new Scheme("https",  
                        new EasySSLSocketFactory(), 8443));  
    ClientConnectionManager connManager = new ThreadSafeClientConnManager(params, schemeRegistry);  
    HttpClient httpClient = new DefaultHttpClient(connManager, params);  
上面的EasySSLSocketFactory类是我们自定义的,主要目的就是让httpclient接受所有的服务器证书,能够正常的进行https数据读取。相关代码如下:

    public class EasySSLSocketFactory implements SocketFactory,  
            LayeredSocketFactory {  
      
        private SSLContext sslcontext = null;  
      
        private static SSLContext createEasySSLContext() throws IOException {  
            try {  
                SSLContext context = SSLContext.getInstance("TLS");  
                context.init(null, new TrustManager[] { new EasyX509TrustManager(  
                        null) }, null);  
                return context;  
            } catch (Exception e) {  
                throw new IOException(e.getMessage());  
            }  
        }  
      
        private SSLContext getSSLContext() throws IOException {  
            if (this.sslcontext == null) {  
                this.sslcontext = createEasySSLContext();  
            }  
            return this.sslcontext;  
        }  
      
         
        public Socket connectSocket(Socket sock, String host, int port,  
                InetAddress localAddress, int localPort, HttpParams params)  
                throws IOException, UnknownHostException, ConnectTimeoutException {  
            int connTimeout = HttpConnectionParams.getConnectionTimeout(params);  
            int soTimeout = HttpConnectionParams.getSoTimeout(params);  
      
            InetSocketAddress remoteAddress = new InetSocketAddress(host, port);  
            SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());  
      
            if ((localAddress != null) || (localPort > 0)) {  
                // we need to bind explicitly  
                if (localPort < 0) {  
                    localPort = 0; // indicates "any"  
                }  
                InetSocketAddress isa = new InetSocketAddress(localAddress,  
                        localPort);  
                sslsock.bind(isa);  
            }  
      
            sslsock.connect(remoteAddress, connTimeout);  
            sslsock.setSoTimeout(soTimeout);  
            return sslsock;  
      
        }  
      
         
        public Socket createSocket() throws IOException {  
            return getSSLContext().getSocketFactory().createSocket();  
        }  
      
         
        public boolean isSecure(Socket socket) throws IllegalArgumentException {  
            return true;  
        }  
      
         
        public Socket createSocket(Socket socket, String host, int port,  
                boolean autoClose) throws IOException, UnknownHostException {  
            return getSSLContext().getSocketFactory().createSocket(socket, host,  
                    port, autoClose);  
        }  
      
        // -------------------------------------------------------------------  
        // javadoc in org.apache.http.conn.scheme.SocketFactory says :  
        // Both Object.equals() and Object.hashCode() must be overridden  
        // for the correct operation of some connection managers  
        // -------------------------------------------------------------------  
      
        public boolean equals(Object obj) {  
            return ((obj != null) && obj.getClass().equals(  
                    EasySSLSocketFactory.class));  
        }  
      
        public int hashCode() {  
            return EasySSLSocketFactory.class.hashCode();  
        }  
    }  
      
    public class EasyX509TrustManager implements X509TrustManager {  
      
        private X509TrustManager standardTrustManager = null;  
      
         
        public EasyX509TrustManager(KeyStore keystore)  
                throws NoSuchAlgorithmException, KeyStoreException {  
            super();  
            TrustManagerFactory factory = TrustManagerFactory  
                   .getInstance(TrustManagerFactory.getDefaultAlgorithm());  
            factory.init(keystore);  
            TrustManager[] trustmanagers = factory.getTrustManagers();  
            if (trustmanagers.length == 0) {  
                throw new NoSuchAlgorithmException("no trust manager found");  
            }  
            this.standardTrustManager = (X509TrustManager) trustmanagers[0];  
        }  
      
         
        public void checkClientTrusted(X509Certificate[] certificates,  
                String authType) throws CertificateException {  
            standardTrustManager.checkClientTrusted(certificates, authType);  
        }  
      
         
        public void checkServerTrusted(X509Certificate[] certificates,  
                String authType) throws CertificateException {  
            if ((certificates != null) && (certificates.length == 1)) {  
                certificates[0].checkValidity();  
            } else {  
                standardTrustManager.checkServerTrusted(certificates, authType);  
            }  
        }  
      
         
        public X509Certificate[] getAcceptedIssuers() {  
            return this.standardTrustManager.getAcceptedIssuers();  
        }  
    } 



android技术上如有疑问可以问我,有问必答.

爱品茶的盆友,光顾小店(谢谢,能收藏最好了大笑):

http://lancezone.taobao.com


专注移动开发!继续前行~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值