iOS使用Moya向虚拟机部署的OAuth服务获取访问令牌遇证书无效报错的解决方法
问题到底出在哪
你碰到的证书弹窗完完全全是iOS客户端的TLS校验逻辑触发的,和虚拟机服务端配不配置证书校验半毛钱关系没有——服务端只是把无效的HTTPS证书返回给客户端,所有信任校验全是客户端侧的事。
你之前配置半天不生效,纯粹是踩了一堆老开发都容易踩的坑:
- ATS的异常域配置Key写错了,带了
https://前缀,系统压根匹配不到你虚拟机的域名,整个ExceptionDomains块等于白写 - 就算ATS配置对了,
NSAllowsArbitraryLoads也管不了无效证书:这个开关只是允许HTTP明文请求、放宽TLS最低版本要求,碰到自签、域名不匹配的不受信任证书,该拦还是拦 - 你初始化Moya的时候用的是裸默认的MoyaProvider,底层走的是Alamofire默认的Session,默认开了严格证书校验,碰到不受信任的证书就会触发系统原生的那个“是否仍然连接”的弹窗
分步落地的解决方案
1. 先修掉现有配置里的低级错误
- 调整Info.plist的ATS配置,把异常域的Key从带https前缀的
https://server.nb改成纯域名server.nb,否则整个ExceptionDomains的规则不会被系统识别 - 修正MyApi枚举的URL逻辑:baseURL只保留服务根地址
https://server.nb/api,把接口路径挪到path字段里写为oauth/token,不要把完整接口路径塞到baseURL中 - 删掉Content-Type值前面的多余空格,改成
"application/x-www-form-urlencoded",否则严格的服务端会直接拒绝请求,返回媒体类型不支持的错误 - 你之前写的URLEncoding配置是对的,OAuth的令牌接口要求表单体编码,这部分不需要改
2. 自定义带证书信任逻辑的Moya Provider
默认MoyaProvider用的Alamofire Session是严格校验证书的,必须自定义Session、对目标开发环境域名关闭证书校验,才能彻底跳过弹窗。
注意:以下跳过证书校验的逻辑仅适用于开发/测试环境的虚拟机服务,生产环境绝对不能开启,不然被人中间人偷了接口令牌都不知道怎么丢的
先自定义带证书豁免的Session:
import Moya import Alamofire // 仅开发环境使用:对目标测试域名关闭证书校验 let devEnvironmentSession: Session = { let trustManager = ServerTrustManager( evaluators: [ // 替换成你实际的服务端域名,配置为直接跳过证书评估 "server.nb": .disableEvaluation ] ) return Session( configuration: URLSessionConfiguration.default, serverTrustManager: trustManager ) }()
再修改MoyaNetworkService的初始化逻辑,把自定义的Session传给MoyaProvider,替换默认的严格校验逻辑:
struct MoyaNetworkService { private let moyaProvider: MoyaProvider<MyApi> init() { // 关键:传入自定义的带证书豁免的session,不要用默认配置 self.moyaProvider = MoyaProvider<MyApi>(session: devEnvironmentSession) } // 补全回调闭包,方便拿到令牌获取的结果 func fetchOAuthToken(completion: @escaping (Result<Response, MoyaError>) -> Void) { moyaProvider.request(.auth, completion: completion) } }
3. 效果验证
配置完成后,发起/oauth/token请求时:
- 系统不会再弹出证书无效的告警弹窗
- TLS握手会直接跳过对目标域名的证书校验,顺利完成和虚拟机服务端的连接
- 按照你之前写的表单参数配置,正常携带client_id、client_secret、grant_type等参数就能获取到有效访问令牌
避坑提醒
- 不要以为开了
NSAllowsArbitraryLoads就可以跳过证书校验:这个开关仅允许HTTP明文传输、降低TLS版本要求,不会信任任何自签/系统不受信任的证书,必须通过URLSessionDelegate的证书校验逻辑手动放行 - 异常域配置的Key绝对不能带http/https前缀,系统只匹配不带scheme的纯域名格式,带了scheme的配置完全不会被识别
- 上线前一定要把证书校验逻辑改回默认严格模式,不要全局信任所有证书
内容的提问来源于stack exchange,提问作者nivbp
相关产品推荐
相关产品推荐

