Android应用不信任带有有效CA证书的Web服务器问题求助
解决Android SSLHandshakeException:信任锚找不到的问题
问题原因
你的Android应用崩溃是因为系统内置的根证书库中缺少服务器使用的DigiCert RapidSSL Global TLS RSA4096 SHA256 2022 CA1信任锚。浏览器自带了更完整的根证书集合,所以能正常访问,但Android 11及更早版本的系统没有预装这个2022年发布的CA证书,导致SSL握手验证失败。
解决方案
方案1:将CA证书嵌入应用(推荐,安全合规)
把DigiCert的这个CA证书打包到应用中,让应用信任该证书,步骤如下:
- 下载CA证书:获取DigiCert RapidSSL Global TLS RSA4096 SHA256 2022 CA1的PEM格式证书。
- 放置证书文件:将证书文件命名为
digicert_ca.crt,放到app/src/main/res/raw目录下(没有raw目录就新建)。 - 编写SSL工具类:创建加载自定义证书的工具类:
import android.content.Context import java.io.InputStream import java.security.KeyStore import java.security.cert.CertificateFactory import javax.net.ssl.SSLContext import javax.net.ssl.TrustManagerFactory import javax.net.ssl.X509TrustManager object SSLUtils { fun getCustomSSLContext(context: Context): SSLContext { val certInputStream: InputStream = context.resources.openRawResource(R.raw.digicert_ca) val certificateFactory = CertificateFactory.getInstance("X.509") val certificate = certificateFactory.generateCertificate(certInputStream) val keyStore = KeyStore.getInstance(KeyStore.getDefaultType()).apply { load(null, null) setCertificateEntry("digicert_ca", certificate) } val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()).apply { init(keyStore) } return SSLContext.getInstance("TLS").apply { init(null, trustManagerFactory.trustManagers, null) } } }
- 修改网络请求代码:
推荐使用OkHttp(更简洁),先在app/build.gradle中添加依赖:
implementation("com.squareup.okhttp3:okhttp:4.12.0")
然后更新请求函数:
import okhttp3.OkHttpClient import okhttp3.Request import java.io.IOException fun getNewestVersion(context: Context): String { val sslContext = SSLUtils.getCustomSSLContext(context) val client = OkHttpClient.Builder() .sslSocketFactory(sslContext.socketFactory, sslContext.trustManagers[0] as X509TrustManager) .build() val request = Request.Builder() .url("https://www.myserver.com/info") .build() client.newCall(request).execute().use { response -> if (!response.isSuccessful) throw IOException("请求失败:$response") return response.body?.string()?.trim() ?: "" } }
如果坚持使用原生URLConnection,代码如下:
import android.content.Context import java.net.URL import javax.net.ssl.HttpsURLConnection fun getNewestVersion(context: Context): String { val sslContext = SSLUtils.getCustomSSLContext(context) val url = URL("https://www.myserver.com/info") val connection = url.openConnection() as HttpsURLConnection connection.sslSocketFactory = sslContext.socketFactory return connection.inputStream.bufferedReader().use { it.readText().trim() } }
方案2:适配Android 12+
如果你的应用最低兼容版本(minSdkVersion)设为31(Android 12)及以上,系统已经预装了该CA证书,无需额外处理,只需确保请求在子线程执行(你的代码使用了DefaultDispatcher,已经满足)。
注意事项
- 绝对不要禁用SSL验证:不要编写信任所有证书的代码,这会导致应用面临中间人攻击的严重安全风险,仅可用于本地测试。
- 确保证书格式正确:必须是PEM格式的X.509证书,避免因格式错误导致加载失败。
内容的提问来源于stack exchange,提问作者Mav Rick
相关产品推荐
相关产品推荐

