Ktor-client使用IP地址发起HTTPS请求遇主机名未验证问题
解决Ktor Client使用IP访问HTTPS时的Hostname验证错误
问题原因
你配置的TrustManager仅跳过了证书信任校验,但OkHttp默认会执行主机名验证:检查服务器证书的SAN(Subject Alternative Name)或CN(Common Name)字段是否包含请求的IP地址。如果证书未绑定目标IP,就会抛出Hostname xxx not verified错误。
解决方案
方案1:临时禁用主机名验证(仅测试环境)
在OkHttp引擎配置中添加自定义hostnameVerifier,直接返回true跳过验证:
engine { config { // 原有SSL配置 val sslContext: SSLContext = SSLContext.getInstance("SSL") sslContext.init(null, trustAllCerts, SecureRandom()) sslSocketFactory(sslContext.socketFactory, trustAllCerts[0] as X509TrustManager) // 跳过主机名验证 hostnameVerifier { _, _ -> true } } }
注意:此方法仅适用于测试环境,生产环境禁用会导致中间人攻击风险。
方案2:自定义验证逻辑(生产环境推荐)
针对特定IP做白名单,同时保留域名请求的默认验证逻辑:
engine { config { // 原有SSL配置... hostnameVerifier { hostname, session -> // 允许指定IP通过验证 hostname == "192.168.1.100" || // 保留默认验证,兼容域名请求 OkHostnameVerifier.INSTANCE.verify(hostname, session) } } }
方案3:修改服务器证书(最安全)
让服务器证书的SAN字段添加目标IP地址,这样默认的主机名验证器就能正常通过,无需修改客户端代码。这是生产环境的最优解。
更换为CIO引擎的配置方式
如果切换到Ktor的CIO引擎,配置逻辑类似:
import io.ktor.client.engine.cio.* val client = HttpClient(CIO) { engine { sslManager = { SSLContext.getInstance("SSL").apply { init(null, trustAllCerts, SecureRandom()) }.socketFactory } hostnameVerifier = { hostname, session -> hostname == "192.168.1.100" || defaultHostnameVerifier.verify(hostname, session) } } }
内容的提问来源于stack exchange,提问作者Patrik Csikós
相关产品推荐
相关产品推荐

