iOS9 收到错误“发生 SSL 错误,无法与服务器建立安全连接”

iOS9 getting error “an SSL error has occurred and a secure connection to the server cannot be made”

自从我用 iOS 9 升级现有项目后,我一直收到错误消息:

An SSL error has occurred and a secure connection to the server cannot be made.

对于 iOS9,Apple 在 iOS 9 中做出了一个激进的决定,作为 App Transport Security (ATS) 的一部分,禁用了来自 iOS 个应用程序的所有不安全的 HTTP 流量。 =12=]

要简单地禁用 ATS,您可以按照以下步骤打开 Info.plist,并添加以下行:

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

尽管允许任意加载 (NSAllowsArbitraryLoads = true) 是一个很好的解决方法,但您不应该完全禁用 ATS,而是启用您想要允许的 HTTP 连接:

<key>NSAppTransportSecurity</key>
<dict>
  <key>NSExceptionDomains</key>
  <dict>
    <key>yourserver.com</key>
    <dict>
      <!--Include to allow subdomains-->
      <key>NSIncludesSubdomains</key>
      <true/>
      <!--Include to allow HTTP requests-->
      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
      <true/>
      <!--Include to specify minimum TLS version-->
      <key>NSTemporaryExceptionMinimumTLSVersion</key>
      <string>TLSv1.1</string>
    </dict>
  </dict>
</dict>

iOS 9 强制使用 HTTPS 的连接为 TLS 1.2 以避免最近的漏洞。在 iOS 8 中甚至支持未加密的 HTTP 连接,因此旧版本的 TLS 也不会产生任何问题。作为解决方法,您可以将此代码片段添加到您的 Info.plist:

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

*参考App Transport Security (ATS)

问题出在服务器端的 ssl 证书上。有什么干扰或证书与服务不匹配。例如,当一个站点具有 www.mydomain.com 的 ssl 证书而您使用的服务在 myservice.mydomain.com 上运行时。那是不同的机器。

似乎 iOS 9.0.2 中断了对有效 HTTPS 端点的请求。我目前的怀疑是它需要 SHA-256 证书,否则会因此错误而失败。

要重现,请使用 safari 检查您的 UIWebView,然后尝试导航到任意 HTTPS 端点:

location.href = "https://d37gvrvc0wt4s1.cloudfront.net/js/v1.4/rollbar.min.js"
// [Error] Failed to load resource: An SSL error has occurred and a secure connection to the server cannot be made. (rollbar.min.js, line 0)

现在尝试去 google(因为他们当然有 SHA-256 证书):

location.href = "https://google.com"
// no problemo

为传输安全添加例外(如上文@stéphane-bruckert 的回答所述)可解决此问题。我还假设完全禁用 NSAppTransportSecurity 也会起作用,尽管我读过完全禁用它会危及您的应用审查。

[编辑] 我发现只要在 NSExceptionDomains 字典中枚举我正在连接的域就可以解决这个问题,即使将 NSExceptionAllowsInsecureHTTPLoads 设置为 true 也是如此。 :\

如果您只是针对特定的域,您可以尝试将其添加到您的应用程序的 Info.plist:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>example.com</key>
        <dict>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <false/>
            <key>NSIncludesSubdomains</key>
            <true/>
        </dict>
    </dict>
</dict>

当我将 HTTPS URL 指定为:https://www.mywebsite.com . However it works fine when I specify it without the three W's as : https://mywebsite.com 时,我遇到了同样的错误。

Xcode 项目 -> 转到 info.plist 并单击 + 按钮然后添加(应用程序传输安全设置)展开,允许任意加载设置为是。谢谢

我的问题是 NSURLConnection,在 iOS9 中已弃用,所以我将所有 API 更改为 NSURLSession,这解决了我的问题。

就我而言,我在模拟器中遇到了这个问题,因为我的计算机日期晚于当前日期。因此,当您遇到 SSL 错误时,也要检查这种情况。

播放时出现以下错误

finished with error [-1200] Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://remote-abcabc-svc.an.abc.com:1935/abr/_definst_/smil:v2/video/492F2F82592F59EA74ABAA6B9D6E6F42/F6B1BD452132329FBACD32730862CAE0/091EAD80FE9BEDD52A2F33840CA3CBAC.v3.eng.smil/playlist.m3u8, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <692A1174-DA1C-4267-9560-9020A79F8458>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <692A1174-DA1C-4267-9560-9020A79F8458>

我确保我在 plist 文件的异常域中添加了条目,并且 NSAllowsArbitraryLoads 设置为 true,但我仍然看到错误。

然后我意识到我正在 URL 使用 https 而不是 http。

我将视频 url 设置为 http,问题已解决。

我在某些网络调用中遇到此错误,而在其他网络调用中则没有。我已连接到 public wifi。该免费 wifi 似乎会篡改某些 URL,因此会出现错误。

当我连接到 LTE 时,错误消失了!

使用这个网站,我输入了我发出请求的服务器地址,并将生成的 SHA 密钥添加到 info.plist。

https://www.ssllabs.com/ssltest/index.html

<key>NSAppTransportSecurity</key>
    <dict>
        <key>NSPinnedDomains</key>
        <dict>
            <key>Your domain here (www.api.com)</key>
            <dict>
                <key>NSPinnedLeafIdentities</key>
                <array>
                    <dict>
                        <key>SPKI-SHA256-BASE64</key>
                        <string>******pfbtB5iNouq********rC8Nrb+AmLFKxV7qgM=</string>
                    </dict>
                </array>
            </dict>
        </dict>
    </dict>

在我的例子中,我打开了网络嗅探应用程序,例如 Charles Proxy 或 Proxyman。