Android网络安全配置致第三方API SSLHandshakeException问题排查
你遇到的CertificateException核心诱因在于:当Android网络安全配置中存在<domain-config>条目时,系统的RootTrustManager会强制要求所有未匹配该规则的网络请求,必须调用带hostname参数的checkServerTrusted重载方法(即checkServerTrusted(X509Certificate[], String, String))。但旧版本的ArcGIS Runtime SDK内部证书验证逻辑,可能调用的是不带hostname的旧版重载方法(checkServerTrusted(X509Certificate[], String)),这就触发了系统的安全校验异常——哪怕公网服务器的证书完全有效。
而你使用<base-config>的配置能正常运行,是因为这个全局配置明确了所有域名的验证规则,系统不会强制要求hostname-aware的验证方法,自然绕过了兼容性问题,但确实降低了全局安全约束。
这里有两个安全且有效的配置方案,你可以根据需求选择:
方案1:为所有涉及的域名添加明确的domain-config
把公网ArcGIS服务器的域名也加入配置,明确它的验证规则(因它有有效证书,无需明文传输):
<?xml version="1.0" encoding="utf-8"?> <network-security-config xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 内网开发服务器:允许明文传输 --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">172.17.1.14</domain> </domain-config> <!-- 公网ArcGIS服务器:禁用明文,信任系统根证书 --> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">your-public-arcgis-domain.com</domain> <trust-anchors> <certificates src="system" /> </trust-anchors> </domain-config> </network-security-config>
每个域名都有明确规则后,系统不会对未匹配域名强制执行特殊验证逻辑,ArcGIS SDK就能正常处理证书校验了。
方案2:保留全局base-config,仅对内网服务器做例外
如果应用可能访问其他公网域名,不想逐个添加domain-config,可以用全局base-config定义默认规则,再给内网服务器加例外:
<?xml version="1.0" encoding="utf-8"?> <network-security-config xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 全局默认配置:禁用明文,信任系统根证书 --> <base-config cleartextTrafficPermitted="false"> <trust-anchors> <certificates src="system" /> </trust-anchors> </base-config> <!-- 内网服务器例外:允许明文传输 --> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">172.17.1.14</domain> </domain-config> </network-security-config>
这个方案既保证了公网请求的安全性,又兼容内网的明文需求,同时避免了系统触发hostname-aware验证的强制要求。
- 检查ArcGIS Runtime SDK版本:如果使用的是较旧版本,建议升级到官方最新版,大概率已经修复了与Android网络安全配置的兼容性问题。
- 避免仅包含单个domain-config且无base-config的配置:这种配置会让Android对所有未匹配域名启用隐式的严格验证规则,极易触发类似兼容性异常。
内容的提问来源于stack exchange,提问作者Plinio.Santos

