jos*_*eph 11 java security ssl android android-sdk-2.3
在我的服务器(生产服务器)中,我有一个goDaddy ssl证书.我有iOS和Android应用程序连接服务器,iOS连接没有问题,Android连接版本4.*一切都很好,但设备2.3.*我总是得到SSLHandshakeException.
我确实喜欢Android开发者页面(https://developer.android.com/training/articles/security-ssl.html).
我已经在stackoverflow中看到了类似的线程(这里),但没有人帮忙.
然后我看到这个线程谈论扩展密钥用法,但在调试时我得到以下信息:
[2]: OID: 2.5.29.37, Critical: false
Extended Key Usage: [ "1.3.6.1.5.5.7.3.1", "1.3.6.1.5.5.7.3.2" ]
Run Code Online (Sandbox Code Playgroud)
所以我猜证书不是"强制"扩展密钥用法.
同样在此线程有一些其他可能的原因,如日期/时间是完全地错了,至极都是不存在的.
考虑到这一点,我现在不知道问题可能在哪里.
有什么建议?
编辑: StackTrace如下:
08-04 16:54:30.139: W/System.err(4832): Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
08-04 16:54:30.149: W/System.err(4832): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:161)
08-04 16:54:30.149: W/System.err(4832): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:664)
08-04 16:54:30.149: W/System.err(4832): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
08-04 16:54:30.159: W/System.err(4832): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474)
Run Code Online (Sandbox Code Playgroud)
我在SO和网络上经历了很多地方来解决这个问题.这是适合我的代码(Android 21):
ByteArrayInputStream derInputStream = new ByteArrayInputStream(app.certificateString.getBytes());
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509","BC");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(derInputStream);
String alias = "alias";//cert.getSubjectX500Principal().getName();
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);
trustStore.setCertificateEntry(alias, cert);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(trustStore, null);
KeyManager[] keyManagers = kmf.getKeyManagers();
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
TrustManager[] trustManagers = tmf.getTrustManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
URL url = new URL(someURL);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(sslContext.getSocketFactory());
Run Code Online (Sandbox Code Playgroud)
app.certificateString 是包含证书的String,例如:
static public String certificateString=
"-----BEGIN CERTIFICATE-----\n" +
"MIIGQTCCBSmgAwIBAgIHBcg1dAivUzANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UE" +
"BhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBE" +
... a bunch of characters...
"5126sfeEJMRV4Fl2E5W1gDHoOd6V==\n" +
"-----END CERTIFICATE-----";
Run Code Online (Sandbox Code Playgroud)
我已经测试过你可以在证书字符串中放置任何字符,如果它是自签名的,只要你保持上面的确切结构.我用笔记本电脑的终端命令行获取了证书字符串.我需要了解更多细节,请告诉我.
小智 5
如果以上所有答案都不起作用,并且在使用 android 30 作为编译和目标 sdk 版本时,您在发布应用程序时遇到任何类型的问题。请从服务器下载您的 ssl .cert 文件。并将其放入 raw 文件夹中。在 XML 文件夹中创建 network_security_config。在应用程序标签内的菜单中使用行
android:networkSecurityConfig="@xml/network_security_config"
并在 network_security_config 文件中使用下面提到的代码。
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">your server domain</domain>
<trust-anchors>
<certificates src="@raw/your server cerificate file name"/>
</trust-anchors>
</domain-config>
</network-security-config>
Run Code Online (Sandbox Code Playgroud)
您的证书的颁发者似乎不在 2.3 设备的信任存储中。
查看您的 GoDaddy 证书的根和中间 ca,并检查您的 2.3 设备上是否存在这些证书。
请参阅http://www.andreabaccega.com/blog/2010/09/23/android-root-certification-authorities-list/以获取 2.3 证书列表。
当只有根 CA 可用时,请确保您的网络服务器还根据请求提供中间证书。
| 归档时间: |
|
| 查看次数: |
48352 次 |
| 最近记录: |