Sil*_*los 5 java ssl android x509certificate sslhandshakeexception
我正在开发一个必须支持API级别16的项目,并要求我对动态URL进行网络调用.我遇到的问题是服务器最近不得不将TLS更新为1.2以实现PCI合规性,默认情况下在Android API 16-19上禁用.虽然启用此功能并不困难,但我遇到了仅针对这些API级别的X509证书问题.
我对它做了很多研究,虽然所有这些链接都很有用:
1)如何在Android应用程序中启用TLS 1.2支持(在Android 4.1 JB上运行)
2)如何使用自签名证书连接到Android(paho客户端)中的Mqtt服务器?
4)允许Java使用不受信任的证书进行SSL/HTTPS连接
6)SSLHandshakeException:未找到证书路径的信任锚.仅适用于Android API <19
他们没有解决我遇到的核心问题,即我看到了这个例外:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:151)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:112)
Caused by: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:409)
at com.android.okhttp.Connection.upgradeToTls(Connection.java:146)
at com.android.okhttp.Connection.connect(Connection.java:107)
at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:294)
at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:503)
at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:136)
at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:110)
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:96)
... 1 more
Run Code Online (Sandbox Code Playgroud)
当我尝试连接到需要TLS1.2的URL时,例如https://www.ssllabs.com/ssltest/viewMyClient.html.
从本质上讲,它归结为TrustManager的一个问题.
以下是获取TrustManager对象的两种不同方法(第一种方法比第二方更安全,因为第二方信任所有证书,这使得SSL成为一个有争议的问题):
第一种方法:
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
Run Code Online (Sandbox Code Playgroud)
第二种方法:
X509TrustManager trustManager = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
Run Code Online (Sandbox Code Playgroud)
然后将它们与此代码一起使用:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
sslContext.init(null, new TrustManager[] { trustManager }, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
Run Code Online (Sandbox Code Playgroud)
如果我在API级别20+上使用第一个TrustManager,上面列出的url将正常工作,页面将加载.如果我在API级别16-19上使用第一个,它将抛出上面列出的异常.
如果我在任何API级别16+上使用第二个TrustManager,该调用将起作用,但是,它在我的应用程序中留下了安全漏洞,因为我现在信任所有证书并让自己对各种攻击持开放态度.
另外另一个注意事项是,虽然上面的示例错误来自Volley库,但在使用具有相同结果的Retrofit时仍然会发生.
因此,我的问题是,如何利用X509TrustManager 在API级别16-19上使用像This One这样的网站,就像在API级别20+上一样?
谢谢你的时间.
| 归档时间: |
|
| 查看次数: |
616 次 |
| 最近记录: |