Android Https请求

网上大多数多Https的处理都是忽略所有证书的校验,大致做法如下:

private void TrustAllHttps() {
        try {
            SSLContext sc = SSLContext.getInstance("TLS");
            sc.init(null, new TrustManager[] { new TrustAllManager() }, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            HttpsURLConnection.setDefaultHostnameVerifier(new TrustHostnameVerifier());
            HttpsURLConnection conn = (HttpsURLConnection) new URL(URL_TEST).openConnection();
            conn.setRequestMethod("POST");// 设置请求类型为post
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.connect();

            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
                Log.d("TAG", line);
            }

        } catch (Exception e) {
            Log.e(this.getClass().getName(), e.getMessage());
        }

    }

    private class TrustHostnameVerifier implements HostnameVerifier {

        // 信任所有主机-对于任何证书都不做检查 
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private class TrustAllManager implements X509TrustManager {

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
        }

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

之前我们也是这么做的,但是存在风险,最近改为单向验证,参考了网上的各种写法,代码如下(都写在一块了,最好自己调整下):

/**
     * HttpsUrlConnection 方式,支持指定**.crt证书验证,此种方式Android官方建议
     * 
     * @throws CertificateException
     * @throws IOException
     * @throws KeyStoreException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     * @throws NoSuchProviderException
     */
    public void initHttpsConnection() {
        try {
            InputStream in = getAssets().open("server.cer");
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            Certificate  cer = certificateFactory.generateCertificate(in);
            System.out.println("ca=" + ((X509Certificate) cer).getSubjectDN());

            // Create a KeyStore containing our trusted CAs
            KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(null);
            keystore.setCertificateEntry("ca", cer);

            // Create a TrustManager that trusts the CAs in our KeyStore
            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
            trustManagerFactory.init(keystore);
            
            // Create an SSLContext that uses our TrustManager
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            
            URL url = new URL(URL);
            HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
            conn.setSSLSocketFactory(sslContext.getSocketFactory());
            conn.setHostnameVerifier(DO_NOT_VERIFY);
            conn.setRequestMethod("POST");// 设置请求类型为post
            conn.setConnectTimeout(10000);// 设置超时时间
            conn.setReadTimeout(50000);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            InputStream input = conn.getInputStream();

            BufferedReader reader = new BufferedReader(new InputStreamReader(input));
            StringBuffer result = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                result.append(line);
                Log.d("TAG", line);
            }
            
        } catch (Exception e) {
            Log.e(this.getClass().getName(), e.getMessage());
        }
    }

    static HostnameVerifier DO_NOT_VERIFY = new HostnameVerifier() {
        // 信任所有主机
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    };

代码基于HttpsURLConnection实现,其他方式也都差不多。

    原文作者:eyow
    原文地址: https://www.jianshu.com/p/7da112f1e5c7
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞