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

Ktor Socket客户端连接自签名服务器报checkServerTrusted错误如何解决?

问题原因

  1. 基础配置不匹配:你代码中连接的服务器IP是192.168.1.5,但网络安全配置中信任的域名是192.168.78.74,二者不一致导致系统级信任配置未生效。
  2. Ktor 1.x版本的TLS实现缺陷:Ktor 1.6.5的TLS握手逻辑默认调用的是双参数checkServerTrusted(X509Certificate[], String)方法,而Android 7+的网络安全配置要求必须调用带主机名的三参数重载checkServerTrusted(X509Certificate[], String, String),否则就会抛出你遇到的异常。

解决步骤

第一步:修正网络安全配置匹配

把network_security_config.xml中的domain改为你实际连接的服务器IP:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <domain-config>
        <domain includeSubdomains="true">192.168.1.5</domain>
        <trust-anchors>
            <certificates src="@raw/my_cert"/>
        </trust-anchors>
    </domain-config>
</network-security-config>

第二步:自定义Ktor TLS配置适配Android要求

在调用tls()方法时传入自定义TLS配置,明确指定服务器主机名,触发系统要求的三参数证书校验逻辑:

// 先定义服务器地址常量
val serverHost = "192.168.1.5"
val serverPort = 8080

socketConnection = aSocket(ActorSelectorManager(Dispatchers.IO))
    .tcp()
    .connect(InetSocketAddress(serverHost, serverPort))
    .tls(
        coroutineContext = Dispatchers.IO,
        config = TLSConfigBuilder().apply {
            // 明确指定服务器主机名,触发三参数的证书校验方法
            serverName = serverHost
        }.build()
    )

如果仍有报错,可以手动实现仅信任你的自签名证书的TrustManager,适配校验规则:

class CustomTrustManager(private val trustedCert: X509Certificate) : X509TrustManager {
    override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) = Unit

    override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {
        checkServerTrusted(chain, authType, null)
    }

    override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?, host: String?) {
        chain ?: throw CertificateException("Certificate chain is empty")
        val serverCert = chain.firstOrNull() ?: throw CertificateException("No server certificate")
        // 校验证书是否和我们信任的自签名证书一致
        if (serverCert.encoded.contentEquals(trustedCert.encoded)) return
        throw CertificateException("Certificate not trusted")
    }

    override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf(trustedCert)
}

然后把自定义TrustManager注入到TLS配置中:

// 读取raw目录下的自签名证书
val certFactory = CertificateFactory.getInstance("X.509")
val trustedCert = resources.openRawResource(R.raw.my_cert).use {
    certFactory.generateCertificate(it) as X509Certificate
}
val customTrustManager = CustomTrustManager(trustedCert)

// 构建TLS配置
config = TLSConfigBuilder().apply {
    serverName = serverHost
    trustManagers = arrayOf(customTrustManager)
}.build()

注意:不要为了省事直接信任所有证书,会导致应用存在中间人攻击风险,仅信任你自己的自签名证书即可。

可选方案:升级Ktor版本

Ktor 2.0及以上版本已经修复了这个TLS校验的兼容问题,如果你的项目可以升级依赖,直接把Ktor版本升到2.x即可,不需要自定义TrustManager,只需要修正IP匹配问题即可正常使用系统网络安全配置。


内容的提问来源于stack exchange,提问作者Michael Dippold

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 07:15:01