如何通过Android安全下面的HTTPs连接

时间:2014-07-14 15:36:27

标签: android http ssl https connection

我在安全套接字层下方有一个使用信任管理器创建隧道的东西,但我不明白允许所有主机名称的影响。谁能解释一下?

有人可以建议我需要在代码中进行哪些更改吗?

        public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory {

            private SSLContext sslcontext = null;

            private 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;
            }

            /**
             * @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(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;

            /**
             * 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[],String authType)
             */
            public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
                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();
            }
            }


        public static HttpClient getNewHttpClient() {
            try {
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(null, null);

                SSLSocketFactory sf = new MySSLSocketFactory(trustStore);
                sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

                HttpParams params = new BasicHttpParams();
                HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
                HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);

                SchemeRegistry registry = new SchemeRegistry();
                registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
                registry.register(new Scheme("https", sf, 443));

                ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);

                return new DefaultHttpClient(ccm, params);
            } catch (Exception e) {
                return new DefaultHttpClient();
            }
        }

1 个答案:

答案 0 :(得分:1)

  

使用AllowAllHostnameVerifier()或   SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER基本上关闭   使用SSL连接时的主机名验证。这是等效的   信任所有证书。

因此您需要更改主机名验证程序:

选项包括:

  1. BrowserCompatHostnameVerifier

    主机名必须与第一个CN或任何一个匹配 主题低价竞标。通配符可以出现在CN和任何一个中 标的ALTS。

    BROWSER_COMPATIBLE和STRICT之间的唯一区别是a 带有BROWSER_COMPATIBLE的通配符(例如* .foo.com“)匹配所有 子域名,包括“a.b.foo.com。

  2. StrictHostnameVerifier

    主机名必须与第一个匹配 CN或任何主题。通配符可以出现在CN中,和 在任何主题中。与IE6的一个分歧就是我们如何 只检查第一个CN。 IE6允许与任何CN进行匹配 当下。我们决定只遵循Sun Java 1.4的脚步 检查第一个CN。 (如果你需要检查所有的CN,请随意 编写自己的实现!)。

    诸如“* .foo.com”之类的通配符仅匹配相同的子域 等级,例如“a.foo.com”。它与更深的子域不匹配 例如“a.b.foo.com”。

  3. 如果要实现其中一种验证不存在的验证,则需要创建自己的主机名验证程序。

  4. Some basic information about Hostname Verification