📜  如何处理Android应用程序中的SSL(HTTPs)认证路径异常?(1)

📅  最后修改于: 2023-12-03 15:24:41.372000             🧑  作者: Mango

如何处理Android应用程序中的SSL(HTTPs)认证路径异常?

1. 什么是SSL(HTTPs)认证路径异常?

在Android应用程序中,当使用HTTPs请求数据时,会进行SSL认证来确保网络安全。SSL认证需要建立信任链路(Trust Path),也就是证书链,如果出现异常则会导致SSL认证失败,导致无法进行网络请求。

SSL(HTTPs)认证路径异常的表现包括但不限于以下几种:

  • javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
  • javax.net.ssl.SSLPeerUnverifiedException: Certificate not verified.
  • javax.net.ssl.SSLException: SSL handshake aborted.
  • javax.net.ssl.SSLException: Connection closed by peer.
2. 处理SSL(HTTPs)认证路径异常的方法
2.1 查看异常信息

在捕获到SSL(HTTPs)认证路径异常时,需要查看异常信息来确定具体的异常原因。异常信息一般包括异常类型和异常信息详情。根据异常信息详情,可以知道是否是证书链问题,如果是,还需要判断是什么原因导致证书链不被信任,是否是证书过期、证书颁发机构不受信任等。

try {
    // 进行网络请求
} catch (SSLException e) {
    e.printStackTrace();
}
2.2 导入证书

当出现证书不被信任时,可以通过导入证书的方式来解决。证书可以是服务器端的证书,也可以是中间证书。我们需要用到Bouncy Castle库,这是一个第三方的加密库,需要在项目中引入。

2.2.1 导入服务器端证书

获取服务器端证书的方式有多种,这里以将证书放在assets文件夹下为例。

// 创建Bouncy Castle库的证书工厂
Security.insertProviderAt(new BouncyCastleProvider(), 1);
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
InputStream inputStream = context.getAssets().open("server.crt");
X509Certificate cert = (X509Certificate) certificateFactory.generateCertificate(inputStream);

// 将证书添加至信任证书管理器
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("server", cert);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

// 进行HTTPs请求
URL url = new URL("https://example.com/");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
HttpsURLConnection httpsURLConnection = (HttpsURLConnection) conn;
httpsURLConnection.setSSLSocketFactory(sslContext.getSocketFactory());

2.2.2 导入中间证书

有些情况下,服务器并不直接提供证书,而是提供了一个中间证书(Intermediate Certificate),需要将中间证书和根证书一起导入。

// 获取根证书
InputStream rootInputStream = context.getAssets().open("root.crt");
X509Certificate rootCert = (X509Certificate) certificateFactory.generateCertificate(rootInputStream);

// 获取中间证书
InputStream intermediateInputStream = context.getAssets().open("intermediate.crt");
X509Certificate intermediateCert = (X509Certificate) certificateFactory.generateCertificate(intermediateInputStream);

// 将证书添加至信任证书管理器
keyStore.setCertificateEntry("root", rootCert);
keyStore.setCertificateEntry("intermediate", intermediateCert);
2.3 禁用证书校验

禁用证书校验虽然可以让应用程序请求到数据,但同时也会将网络请求变得不安全。这种方式只应在开发和调试阶段使用,不能在正式上线的应用程序中使用。

// 禁用证书校验
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { new 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[] {};
    }
}}, new SecureRandom());
3. 总结

SSL(HTTPs)认证路径异常是Android应用程序中常见的问题,应该尽早发现并解决。处理SSL(HTTPs)认证路径异常的方法多种多样,需要根据具体情况选择合适的处理方式。在开发和调试阶段,可以使用禁用证书校验的方式来快速检查应用程序的逻辑是否正确,但同时也需要注意安全问题。