移动端(iOS)接入 封面
Vapor 大型教程

移动端(iOS)接入

Vapor 多数时候在讲服务端,但你的 App 总得有个客户端。这篇短文讲清楚 iOS 接入时最常被卡住的两道关:怎么放开 HTTP 明文请求、怎么信任自签 HTTPS 证书。

一、为什么需要放开 HTTPS 限制

从 iOS 9 起,苹果默认开启 App Transport Security(ATS):App 只能访问 https 且证书链合法的接口,http 明文请求会被直接拦下。

但在开发阶段,你的 Vapor 服务端很可能跑在本地、用的是 http://localhost:8080,或者用了自签名的 HTTPS 证书。这时候请求会全部失败。解决办法分两层:

仅限开发 / 内网:放开 ATS 会降低安全性,正式上架前应当收窄白名单,只放行特定域名,而不是「任意加载」。

二、Info.plist:允许任意网络加载

在 Xcode 里选中项目 → Info 标签页 → 添加 App Transport Security Settings,在其下再添加 Allow Arbitrary Loads 并设为 YES

展开后的结构其实就是这样:

App Transport Security Settings
  |- Allow Arbitrary Loads = YES

等价于在 Info.plist 的 XML 里写成:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsArbitraryLoads</key>
  <true/>
</dict>

设好之后,iOS 就不再拦截明文 http 请求,本地调试能直接打通。

三、URLSession:信任自签 HTTPS 证书

如果服务端是 https 但用的是自签证书,光放开 ATS 还不够——系统仍然会因为「证书不受信任」而失败。这时需要让 URLSession 的代理回调里手动信任该证书。

首先,创建 session 时挂上代理(delegate: self),让证书挑战能被我们截获:

  func session() -> URLSession {
    let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
    return session
  }

然后实现 urlSession(_:didReceive:completionHandler:),把服务端返回的 trust 直接做成凭据并「放行」,等于对所有证书都验证通过:

  //https所有证书都验证通过
  func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
    let credential = URLCredential(trust: challenge.protectionSpace.serverTrust!)
    completionHandler(.useCredential, credential)
  }
原理:这段代码在收到证书挑战时,直接拿 protectionSpace.serverTrust 生成凭据并 .useCredential 放行,相当于「跳过证书校验」。同样只应在调试 / 内网使用,生产环境必须做域名与证书指纹校验。

四、一个现成的 iOS 客户端参考

自己从零搭 iOS 客户端比较繁琐,源站作者放了一个可用的示例仓库,可作为接入 Vapor 后端时的起点:


本系列其他文章