如何在 iOS 9 中启用 App Transport Security 的情况下加载 HTTP URL?

How do I load an HTTP URL with App Transport Security enabled in iOS 9?

因此,昨晚发布的 iOS 新 beta SDK "App Transport Security" 鼓励开发者使用 https 而不是 http。原则上,这是个好主意,我已经在 staging/production 环境中使用了 https。但是,当 iOS 应用程序连接到网络服务时,我没有在我的本地开发环境中设置 https,我在我的笔记本电脑上 运行。

从今天早上的一些尝试来看,URL 加载系统似乎会决定使用 https,即使您给它一个 http URL。有谁知道如何禁用此行为 - 即使只是针对特定的 URLs?

有关完整详细信息,请参阅 Apple 的 Info.plist reference(感谢 @gnasher729)。

您可以在 Info.plist:

中为特定域添加例外
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>testdomain.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSThirdPartyExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
        </dict>
    </dict>
</dict>

每个例外域的所有密钥都是可选的。演讲者没有详细说明任何键,但我认为它们都相当明显。

(来源:WWDC 2015 session 703, “Privacy and Your App”、30:18)

如果您的应用有充分的理由这样做,您也可以使用一个密钥忽略所有应用传输安全限制:

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

如果您的应用没有充分的理由,您可能会面临被拒绝的风险:

Setting NSAllowsArbitraryLoads to true will allow it to work, but Apple was very clear in that they intend to reject apps who use this flag without a specific reason. The main reason to use NSAllowsArbitraryLoads I can think of would be user created content (link sharing, custom web browser, etc). And in this case, Apple still expects you to include exceptions that enforce the ATS for the URLs you are in control of.

If you do need access to specific URLs that are not served over TLS 1.2, you need to write specific exceptions for those domains, not use NSAllowsArbitraryLoads set to yes. You can find more info in the NSURLSesssion WWDC session.

Please be careful in sharing the NSAllowsArbitraryLoads solution. It is not the recommended fix from Apple.

kcharwood(感谢@marco-tolman)

因为已接受的答案提供了必需的信息,以及有关使用和 disabling App Transport Security one can find more on this 的更多信息。

对于每域例外,将这些添加到 Info.plist:

<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>

但是如果我不知道我需要使用的所有不安全域怎么办?Info.plist

中使用以下键
<key>NSAppTransportSecurity</key>
<dict>
  <!--Include to allow all connections (DANGER)-->
  <key>NSAllowsArbitraryLoads</key>
      <true/>
</dict>

For more detail you can get from this link.

编译@adurdin 和@User 给出的答案

将以下内容添加到您的 info.plist 并更改 localhost.com 为您相应的域名,您也可以添加多个域名:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSExceptionDomains</key>
    <dict>
        <key>localhost.com</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <false/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <false/>
            <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
            <true/>
            <key>NSThirdPartyExceptionMinimumTLSVersion</key>
            <string>TLSv1.2</string>
            <key>NSRequiresCertificateTransparency</key>
            <false/>
        </dict>
    </dict>
</dict>
</plist>

你info.plist一定是这样的:

如果您只想为本地开发服务器禁用应用程序传输策略,那么以下解决方案很有效。当您无法或不切实际地设置 HTTPS 时(例如,使用 Google App Engine 开发服务器时),它很有用。

正如其他人所说,绝对不应为生产应用关闭 ATP。

1) 为调试使用不同的 plist

复制你的 Plist 文件和 NSAllowsArbitraryLoads。使用此 Plist 进行调试。

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

2) 排除本地服务器

或者,您可以使用单个 plist 文件并排除特定服务器。但是, 因此您可能需要改用服务器名称(在“系统偏好设置”->“共享”中找到,或在您的本地 DNS 中配置)。

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>server.local</key>
        <dict/>
        <key>NSExceptionAllowsInsecureHTTPLoads</key>
        <true/>
    </dict>
</dict>

以上配置对我不起作用。我尝试了很多键的组合,这个很好用:

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

已关注

我已经通过在 info.plist 中添加一些密钥解决了这个问题。 我遵循的步骤是:

  1. 打开了我的项目info.plist文件

  2. 添加了一个名为 NSAppTransportSecurity 的密钥作为 Dictionary

  3. 添加了一个名为 NSAllowsArbitraryLoads 的子项作为 Boolean,并将其值设置为 YES,如下图所示。

清理项目,现在一切都运行和以前一样好了。

参考 .

我已经解决为plist文件。

  1. 添加 NSAppTransportSecurity:字典。
  2. 添加名为“NSAllowsArbitraryLoads”的子项作为布尔值:是

以下是对我有用的方法:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
    <key>NSExceptionDomains</key>
    <dict>
        <key><!-- your_remote_server.com / localhost --></key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSExceptionAllowsInsecureHTTPLoads</key>
            <true/>
            <key>NSExceptionRequiresForwardSecrecy</key>
            <true/>
        </dict>
    <!-- add more domain here -->
    </dict>
</dict>

我只是想添加这个来帮助其他人并节省一些时间:

如果您正在使用:CFStreamCreatePairWithSocketToHost。确保您的 host.plist 中的相同,或者如果您有单独的套接字域,只需将其添加到那里即可。

CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)/*from .plist*/, (unsigned int)port, &readStream, &writeStream);

希望这对您有所帮助。干杯。 :)