Android Https访问(HttpClient,Httpurlconnect,Okhttp)

Https比http有着更高的安全性.传送加密信息.有单向认证和双向认证.其中如果信任所有证书的话 那么无需将证书放入android asset文件夹下.如果不是,则需放入其文件夹中.httpclinet需要的是SSLSocketFactory 而httpurlconnect和okhttp则需要SSLContext.
一.HttpClient
1.信任所有证书(不建议)

public static SSLSocketFactory getSslSocketFactoryAll(Context context) {
    try {
        KeyStore trustStore = KeyStore.getInstance(KeyStore
                    .getDefaultType());
        trustStore.load(null, null);
        SSLSocketFactory sf = new SSLSocketFactoryAll(trustStore);
        sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); //允许所有主机
        return sf;
    } catch (Exception e) {
        return null;
    }
}

/**
     * 自定义类 信任所有证书
     * **/
public static class SSLSocketFactoryAll extends SSLSocketFactory {
    SSLContext sslContext = SSLContext.getInstance("TLS");

    public SSLSocketFactoryAll(KeyStore truststore)
                throws NoSuchAlgorithmException, KeyManagementException,KeyStoreException, UnrecoverableKeyException {
        super(truststore);
        TrustManager tm = new X509TrustManager() {
        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] chain,String authType)throws java.security.cert.CertificateException {
                }
            @Override
            public void checkServerTrusted(
                        java.security.cert.X509Certificate[] chain,
                        String authType)
                        throws java.security.cert.CertificateException {
                }
            };
            sslContext.init(null, new TrustManager[] { tm }, null);
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port,
            boolean autoClose) throws IOException, UnknownHostException {

    return sslContext.getSocketFactory().createSocket(socket, host,port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

2.信任指定的证书

public static SSLSocketFactory getSslSocketFactory(Context context) {
    try {
        // 服务器端需要验证的客户端证书(双向认证时需要)
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 客户端信任的服务器端证书
        KeyStore trustStore = KeyStore.getInstance("PKCS12", "BC");
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        InputStream in = context.getResources().getAssets().open("12.crt");//加载服务端证书
        //InputStream ksIn = context.getResources().getAssets()     .open(KEY_STORE_CLIENT_PATH);//加载客户端给服务端自己的证书(双向)
        Certificate ca = cf.generateCertificate(in);
        //keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());//加载客户端证书(双向认证时候)
        trustStore.load(null, null);
        trustStore.setCertificateEntry("trust", ca);
        return new SSLSocketFactory(trustStore);
    }catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

按照需求 将上面返回的SSLSocketFactory加载到httpclient中,实现https连接

public static HttpClient getSslSocketFactoryHttp(Context context, int port) {
        HttpClient httpsClient = new DefaultHttpClient();
        SSLSocketFactory sslSocketFactory = getSslSocketFactory(context);
        //SSLSocketFactory sslSocketFactory=getSslSocketFactoryAll(context);
        // 设置http https支持
        if (sslSocketFactory != null) {
            Scheme sch = new Scheme("https", sslSocketFactory, port);//端口默认443
            httpsClient.getConnectionManager().getSchemeRegistry()
                    .register(sch);
            httpsClient.getConnectionManager().getSchemeRegistry()
            .register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        }
        return httpsClient;
    }

二.HttpUrlConnect,OkHttp实现方式
1.信任所有证书(不推荐)

public static SSLContext getAllSslContext() {
        SSLContext sslContext;
        try {
            sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);
            //信任所有证书写法(不推荐)

            sslContext.init(null, new TrustManager[] { new X509TrustManager() {

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0,
                        String arg1) throws CertificateException {

                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0,
                        String arg1) throws CertificateException {

                }
            } }, new SecureRandom());
            return sslContext;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

2.信任特定证书

private static SSLContext getSSLContext(Context context) {
        try {

            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            InputStream in = context.getResources().getAssets().open("12.crt");
            Certificate ca = cf.generateCertificate(in);

            // 服务器端需要验证的客户端证书
            KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
            // 客户端信任的服务器端证书
            KeyStore trustStore = KeyStore.getInstance(KEY_STORE_TYPE_BKS);

            //读取客户端证书(asset文件夹)
            //          InputStream ksIn = context.getResources().getAssets()
            //                  .open(KEY_STORE_CLIENT_PATH);
            //           context.getResources()//----------其他路径
            //           .openRawResource(R.drawable.kclient),CLIENT_KET_PASSWORD.toCharArray()); 
            //读取服务端证书(asset文件夹)
            InputStream tsIn = context.getResources().getAssets()
                    .open(KEY_STORE_TRUST_PATH);
            try {
                //加载客户端载证书和私钥
                //              keyStore.load(ksIn, KEY_STORE_PASSWORD.toCharArray());
                //加载服务端端载证书和私钥
                //trustStore.load(tsIn, KEY_STORE_TRUST_PASSWORD.toCharArray());
                trustStore.load(null, null);
                trustStore.setCertificateEntry("ca", ca);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    //                  ksIn.close();
                } catch (Exception ignore) {
                }
                try {
                    tsIn.close();
                } catch (Exception ignore) {
                }
            }
            SSLContext sslContext = SSLContext.getInstance(CLIENT_AGREEMENT);//取得SSL的SSLContext实例
            //取得KeyManagerFactory和TrustManagerFactory的X509密钥管理器实例 
            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());
            //初始化密钥管理器 
            trustManagerFactory.init(trustStore);
            KeyManagerFactory keyManagerFactory = KeyManagerFactory
                    .getInstance("X509");
            keyManagerFactory.init(keyStore, KEY_STORE_PASSWORD.toCharArray());
            //          sslContext.init(keyManagerFactory.getKeyManagers(),
            //                  trustManagerFactory.getTrustManagers(), null);
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

            return sslContext;
        } catch (Exception e) {
            Log.e("tag", e.getMessage(), e);
        }
        return null;
    }

通过上面不同的方式 将返回的SSLContext加入到HttpUrlConnect,OkHttp
1.HttpUrlConnect

/**
     * 获取HttpsURLConnection
     *
     * @param context 上下文
     * @param url     连接url
     * @param method  请求方式
     * @return HttpsURLConnection
     */
    public static HttpsURLConnection getHttpsURLConnection(Context context,
            String url, String method) {
        URL u;
        HttpsURLConnection connection = null;
        try {
            SSLContext sslContext = getSSLContext(context);
            //          SSLContext sslContext=getAllSslContext();
            if (sslContext != null) {
                u = new URL(url);
                connection = (HttpsURLConnection) u.openConnection();
                connection.setRequestMethod(method);//"POST" "GET"
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setUseCaches(false);
                connection.setRequestProperty("Content-Type",
                        "binary/octet-stream");
                connection.setSSLSocketFactory(sslContext.getSocketFactory());
                connection.setConnectTimeout(30000);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connection;
    }

2.OkHttp

/**
     * 获取SSL认证需要的HttpClient
     *
     * @param context 上下文
     * @return OkHttpClient
     */
        public static OkHttpClient getSSLContextHttp(Context context) {
            OkHttpClient client = new OkHttpClient();
            SSLContext sslContext = getSSLContext(context);
            if (sslContext != null) {
                client.setSslSocketFactory(sslContext.getSocketFactory());
            }
            return client;
        }

至此就完成了android客户端对于Https访问的需求.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值