Android HttpsURLConnection 在模拟器上使用自签名证书,但在真实设备上不行

Android HttpsURLConnection works with self-signed certificate on emulator but not on real device

我使用此命令为 EC2 实例上的 nginx 服务器 运行 创建了一个自签名证书

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/selfsigned.key -out /etc/ssl/certs/selfsigned.crt

作为通用名称(例如服务器 FQDN 或您的名称)我使用了 Public EC2 实例的 DNS,类似于 ec2-somenumber.region.compute.amazonaws.com

我使用此代码来解决信任问题, 我将 selfsigned.crt 复制到应用程序原始文件夹并以这种方式使用它:

CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream caInput = getResources().openRawResource(R.raw.selfsigned);
Certificate ca = cf.generateCertificate(caInput);

// 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 = SSLContext.getInstance("TLS");
_sslContext.init(null, tmf.getTrustManagers(), null);

URL url = new URL("https://ec2-somenumber.region.compute.amazonaws.com");
HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setSSLSocketFactory(_sslContext.getSocketFactory());

现在它在模拟器上运行得很好,但是当我尝试在真实设备上调试它时,它给了我这个错误:

 javax.net.ssl.SSLPeerUnverifiedException: Hostname ec2-somenumber.region.compute.amazonaws.com not verified

我在 stackoverlow 上阅读了很多问题,实际上我不想覆盖 hostnameVerifier,直到我明白为什么它可以在模拟器上运行但不能在真实设备上运行。

你有什么建议吗?

谢谢

如果您遇到同样的问题,请参考此link生成证书。

为了使自签名证书在真实设备上工作,我需要在我用于创建证书的 ssl.conf 文件中像这样指定主题备用名称

[alt_names]
DNS.1   = ec2-somenumber.region.compute.amazonaws.com