You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用不信任带有有效CA证书的Web服务器问题求助

解决Android SSLHandshakeException:信任锚找不到的问题

问题原因

你的Android应用崩溃是因为系统内置的根证书库中缺少服务器使用的DigiCert RapidSSL Global TLS RSA4096 SHA256 2022 CA1信任锚。浏览器自带了更完整的根证书集合,所以能正常访问,但Android 11及更早版本的系统没有预装这个2022年发布的CA证书,导致SSL握手验证失败。

解决方案

方案1:将CA证书嵌入应用(推荐,安全合规)

把DigiCert的这个CA证书打包到应用中,让应用信任该证书,步骤如下:

  1. 下载CA证书:获取DigiCert RapidSSL Global TLS RSA4096 SHA256 2022 CA1的PEM格式证书。
  2. 放置证书文件:将证书文件命名为digicert_ca.crt,放到app/src/main/res/raw目录下(没有raw目录就新建)。
  3. 编写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)
        }
    }
}
  1. 修改网络请求代码:
    推荐使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 13:35:22