Android端关于HTTPS的认证---->可用

1.关于HTTPS

HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。

2.普通的HTTP post请求

public void requestPost(Map, String> params){

    HttpURLConnection httpURLConnection = null;
    String result = null;
    try {
        //合成参数
        byte [] requestParams = generateParams(params);
        URL url = new URL(requestUrl);
        httpURLConnection = (HttpURLConnection) url.openConnection();
        httpURLConnection.setConnectTimeout(60*1000);
        httpURLConnection.setReadTimeout(60*1000);
        httpURLConnection.setDoOutput(true);
        httpURLConnection.setDoInput(true);
        httpURLConnection.setUseCaches(false);
        httpURLConnection.setRequestMethod("POST");
        httpURLConnection.setInstanceFollowRedirects(true);
        httpURLConnection.connect();
        DataOutputStream dos = new DataOutputStream(httpURLConnection.getOutputStream());
        dos.write(requestParams);
        dos.flush();
        dos.close();
        if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
            result = stream2string(httpURLConnection.getInputStream());
        }else {
            Log.e(TAG, "requestPost: 请求失败--->"+httpURLConnection.getResponseCode());
        }
        httpURLConnection.disconnect();
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
当请求的接口地址变为HTTPS类型的话,会抛出如下异常

12-17 14:08:38.590 18126-18188/? W/System.err: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.SocketConnector.connectTls(SocketConnector.java:212)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.Connection.connect(Connection.java:1322)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.Connection.connectAndSetOwner(Connection.java:1410)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.OkHttpClient$1.connectAndSetOwner(OkHttpClient.java:131)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.nextConnection(HttpEngine.java:484)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:465)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:371)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:476)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:118)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.connect(DelegatingHttpsURLConnection.java:89)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:25)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.binguokeji.sdk.library.SimpleNetHelper.post(***.java:232)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.binguokeji.sdk.library.Workflow$1.run(***.java:42)
12-17 14:08:38.590 18126-18188/? W/System.err:     at java.lang.Thread.run(Thread.java:818)
12-17 14:08:38.590 18126-18188/? W/System.err: Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:324)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:225)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:115)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:643)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
12-17 14:08:38.590 18126-18188/? W/System.err:     at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:353)
12-17 14:08:38.590 18126-18188/? W/System.err:     ... 14 more
12-17 14:08:38.590 18126-18188/? W/System.err: Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
12-17 14:08:38.590 18126-18188/? W/System.err:     ... 20 more

有道上翻译的错误信息为----->没有找到认证路径的信任锚。   就是因为HTTPS请求有一层ssl加密协议,没有认证的话是不能随意访问的

3.为HTTPS请求设置信任证书

public void setCertificates(HttpsURLConnection httpsURLConnection , InputStream... certificates) {
    try {
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        int index = 0;
        for (InputStream certificate : certificates) {
            String certificateAlias = Integer.toString(index++);
            keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
            try {
                if (certificate != null)
                    certificate.close();
            } catch (IOException e) {

            }
        }
        SSLContext sslContext = SSLContext.getInstance("TLS");
        TrustManagerFactory trustManagerFactory =
                TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(keyStore);
        sslContext.init(null, trustManagerFactory.getTrustManagers(), new SecureRandom());
        httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }

}
在上边post请求的时候做一下判断

URL url = new URL(requestUrl);
if (url.getProtocol().toUpperCase().equals("HTTPS")){
    httpsURLConnection = (HttpsURLConnection) url.openConnection();
    setCertificates(httpsURLConnection , new ByteArrayInputStream("信任证书的key".getBytes("UTF-8"));
    httpURLConnection = httpsURLConnection;
}
httpURLConnection = (HttpURLConnection) url.openConnection();
这样就可以实现HTTPS类型地址的访问了

你可能感兴趣的:(android开发)