几个月前我在做一个项目时也遇到了同样的情况。我有本地服务器用于使用自签名证书进行开发。这是我的 android 代码,它对我有用:
final HttpsURLConnection https = (HttpsURLConnection) requestedUrl.openConnection();
try {
https.setConnectTimeout(timeout);
https.setReadTimeout(timeout);
https.setRequestMethod(method);
if (sslSocketFactory != null) {
https.setSSLSocketFactory(sslSocketFactory);
}
https.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier();
return hv.verify("localhost", session);
}
});
...
我记得,有一件棘手的事情 - 服务器的自签名证书是为名称“localhost”编写的,但在 android 中,HTTPS 请求是使用 IP 地址发出的,这是导致拒绝服务器证书的问题。
并加载客户端证书(在我的例子中,它存储在 android 设备上的 .p12 文件中):
public static SSLContext loadCertificate(String password)
throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException,
UnrecoverableKeyException, KeyManagementException {
final FileInputStream fis = new FileInputStream(new File(CERT_FILE_DIRECTORY, CERT_FILE_NAME));
final KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(fis, password.toCharArray());
final KeyManagerFactory kmf = KeyManagerFactory.getInstance("X509");
kmf.init(keyStore, null);
final KeyManager[] keyManagers = kmf.getKeyManagers();
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, new TrustManager[]{new MyTrustManager()}, null);
return sslContext;
}
然后清空 MyTrustManager:
public class MyTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
有了这一切,我能够通过 HTTPS 使用自签名证书连接到我的本地服务器。