【发布时间】:2017-02-16 13:57:30
【问题描述】:
我有一个从 3rd 方网站下载文档的应用程序(离线浏览)。
我使用的是标准的 HttpUrlConnection。
它曾经像魅力一样工作,但自从升级到 Nougat 后,其中一个站点产生了非常一致的 SSLHandshakeException,其他站点运行正常。
我尝试使用新的应用证书,但没有成功。 我什至尝试过“信任所有证书”TrustManager 的老把戏。没有运气。 TrustManager id 甚至不查询。
虽然我注意到此服务器使用的是相当旧的密码。
...
New, TLSv1/SSLv3, Cipher is RC4-MD5
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : RC4-MD5
...
这可能是我遇到麻烦的原因吗?如果是的话,我该如何将此密码添加到我的连接中?
谢谢
编辑 1:该应用针对 SDK 22 并针对 API 22 进行编译
编辑 2: 代码被破解了一点,以使用“强制”CA(使用站点证书构建)进行测试,并使用“信任所有”信任管理器进行测试。 需要注意的是,在使用时,永远不会使用“trust all”管理器。
SSLContext sslContext = null;
if (testWitCa) {
Certificate ca = null;
try {
ca = cf.generateCertificate(caInput);
Log.v(this, "ca = " + ((X509Certificate) ca).getSubjectDN());
} finally {
caInput.close();
}
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
} else {
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
Log.v(FileDownloader.this, "Checking client with %s", authType);
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
Log.v(FileDownloader.this, "Checking server with %s", authType);
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustAllCerts, null);
}
URL url = new URL(fromUrl);
HttpURLConnection httpConn;
httpConn = (HttpsURLConnection) url.openConnection();
if (sslContext != null) {
((HttpsURLConnection) httpConn).setSSLSocketFactory(sslContext.getSocketFactory());
}
responseCode = httpConn.getResponseCode();
我也尝试过使用以下安全配置文件(Thawte G3 站点的根 CA):
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config>
<trust-anchors>
<certificates src="@raw/site_ca"/>
<certificates src="@raw/thawte_g3_ca"/>
<certificates src="system"/>
</trust-anchors>
</base-config>
</network-security-config>
【问题讨论】:
-
我猜您的目标是 API 24。针对 API 24 时,网络安全方面有一些变化。我认为简单的解决方法是针对 API 23。试一试,看看是否有帮助。
-
您能否发布使用蹩脚密码执行与网站连接的代码?
-
我在 Exchange 2007 服务器上遇到了完全相同的问题。你最后找到解决办法了吗?
-
你好。你找到解决办法了吗?
-
@Andigor 不,走另一条路。
标签: android ssl sslhandshakeexception android-7.0-nougat