如何使用NSIncludesSubdomains实现任意多级子域名证书固定
苹果原生NSPinnedDomains的静态配置本身不支持任意层级子域的自动匹配,有两个核心限制:
NSIncludesSubdomains开启后仅能覆盖当前域名的直接下一级子域,无法匹配两级及以上的嵌套子域- 通配符
*.仅支持匹配单级子域,*.backend.com仅能匹配x.backend.com这类单级子域,无法匹配x.y.backend.com这类多级嵌套域名
以下是两种可行的落地方案:
方案1:分层补全Info.plist静态规则
如果你的业务用到的子域层级是固定可控的,可以按层级补全父域的固定配置,每一级父域都开启NSIncludesSubdomains即可覆盖下一级子域,示例配置如下:
<key>NSPinnedDomains</key> <dict> <!-- 根域配置,覆盖xxx.backend.com --> <key>backend.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <!-- 此处填写你的证书/公钥固定配置 --> </dict> <!-- 测试环境父域配置,覆盖xxx.test-staging.backend.com --> <key>test-staging.backend.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <!-- 此处复用同环境的证书/公钥固定配置 --> </dict> <!-- 开发环境父域配置,覆盖xxx.test-development.backend.com --> <key>test-development.backend.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <!-- 此处复用同环境的证书/公钥固定配置 --> </dict> <!-- 按需新增更高层级的父域配置,比如要覆盖xxx.images.test-staging.backend.com就新增images.test-staging.backend.com的配置 --> <key>images.test-staging.backend.com</key> <dict> <key>NSIncludesSubdomains</key> <true/> <!-- 复用配置即可 --> </dict> </dict>
该方案无需修改业务代码,适合子域层级固定的场景,劣势是子域层级完全随机的场景下配置量会非常大。
方案2:代码层面实现动态证书校验
如果子域层级完全动态无法枚举,直接放弃Info.plist的静态固定配置,通过URLSessionDelegate的认证挑战代理方法手动实现校验逻辑:
- 在
urlSession(_:didReceive:completionHandler:)方法中提取服务端返回的证书链,取出公钥或证书本身计算哈希值 - 手动判断当前请求的域名是否属于你信任的根域(比如判断是否以
.backend.com结尾,支持任意层级匹配) - 哈希校验和域名校验都通过则继续请求,否则直接中断请求
该方案灵活度最高,完全不受系统静态配置规则的限制,可实现任意层级子域的匹配,劣势是需要自行处理证书校验全流程,需注意规避逻辑漏洞导致的安全风险。
内容的提问来源于stack exchange,提问作者dirtydanee
相关产品推荐
相关产品推荐

