天天看點

Android ignore https certificate verification

通過Https通路的時候經常會遇到"Not trusted Server Certificate"的問題,有人說在3.0上面沒有這個問題,可能已經改進了,在2.2及以前的版本中有這個問題。

StackOverflow上也有相關的方案,我整理了一下。

我将注冊的步驟封裝到DefaultHttpClient子類中了,這樣看上去更清晰一些,你也可以

直接執行個體化DefaultHttpClient的方法。

SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme ("https", sslf, 443));  

SingleClientConnManager cm = new  

SingleClientConnManager(post.getParams(), schemeRegistry);  

HttpClient client = new DefaultHttpClient(cm, post.getParams()); 

/** 

 * @author Brant 

 * @decription 

 */ 

public class SSLHttpClient extends DefaultHttpClient { 

    @Override 

    protected ClientConnectionManager createClientConnectionManager() { 

        SchemeRegistry registry = new SchemeRegistry(); 

        registry.register(new Scheme("http", PlainSocketFactory 

                .getSocketFactory(), 80)); 

//443是Https的預設端口,如果網站配置的端口不一樣,這裡要記着改一下

        registry.register(new Scheme("https", new EasySSLSocketFactory(), 443)); 

        return new SingleClientConnManager(getParams(), registry); 

    } 

    public static SSLHttpClient getInstance() { 

        SSLHttpClient client = new SSLHttpClient(); 

        client.setCookieStore(mCookie); 

        return client; 

import java.io.IOException; 

import java.net.InetAddress; 

import java.net.InetSocketAddress; 

import java.net.Socket; 

import java.net.UnknownHostException; 

import javax.net.ssl.SSLContext; 

import javax.net.ssl.SSLSocket; 

import javax.net.ssl.TrustManager; 

import org.apache.http.conn.ConnectTimeoutException; 

import org.apache.http.conn.scheme.LayeredSocketFactory; 

import org.apache.http.conn.scheme.SocketFactory; 

import org.apache.http.params.HttpConnectionParams; 

import org.apache.http.params.HttpParams; 

 * This socket factory will create ssl socket that accepts self signed 

 * certificate 

 *  

 * @author olamy 

 * @version $Id: EasySSLSocketFactory.java 765355 2009-04-15 20:59:07Z evenisse 

 *          $ 

 * @since 1.2.3 

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; 

    /** 

     * @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, 

     *      java.lang.String, int, java.net.InetAddress, int, 

     *      org.apache.http.params.HttpParams) 

     */ 

    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; 

     * @see org.apache.http.conn.scheme.SocketFactory#createSocket() 

    public Socket createSocket() throws IOException { 

        return getSSLContext().getSocketFactory().createSocket(); 

     * @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket) 

    public boolean isSecure(Socket socket) throws IllegalArgumentException { 

        return true;//不判斷socket,直接傳回true

     * @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, 

     *      java.lang.String, int, boolean) 

    public Socket createSocket(Socket socket, String host, int port, 

            boolean autoClose) throws IOException, UnknownHostException { 

//return getSSLContext().getSocketFactory().createSocket();

//will get java.io.IOException: SSL handshake failure: I/O error

//during system call, Broken pipe 

        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(); 

import java.security.KeyStore; 

import java.security.KeyStoreException; 

import java.security.NoSuchAlgorithmException; 

import java.security.cert.CertificateException; 

import java.security.cert.X509Certificate; 

import javax.net.ssl.TrustManagerFactory; 

import javax.net.ssl.X509TrustManager; 

 * @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse 

public class EasyX509TrustManager implements X509TrustManager { 

    private X509TrustManager standardTrustManager = null; 

     * Constructor for EasyX509TrustManager. 

    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]; 

     * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[], 

     *      String authType) 

    public void checkClientTrusted(X509Certificate[] certificates, 

            String authType) throws CertificateException { 

        standardTrustManager.checkClientTrusted(certificates, authType); 

     * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[], 

    public void checkServerTrusted(X509Certificate[] certificates, 

        if ((certificates != null) && (certificates.length == 1)) { 

            certificates[0].checkValidity(); 

        } else { 

            standardTrustManager.checkServerTrusted(certificates, authType); 

     * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers() 

    public X509Certificate[] getAcceptedIssuers() { 

        return this.standardTrustManager.getAcceptedIssuers(); 

然後直接執行個體化SSLHttpClient就可以想Http一樣執行HttpGet和HttpPost方法了,希望能有所幫助:)。

本文轉自 breezy_yuan 51CTO部落格,原文連結:http://blog.51cto.com/lbrant/795636,如需轉載請自行聯系原作者

繼續閱讀