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

468

因此,昨晚发布的iOS新版beta SDK中有一个名为“应用程序传输安全”的功能,鼓励开发人员使用https而不是http。原则上,这是一个很好的想法,我已经在我们的预发布/生产环境中使用https。然而,在我的本地开发环境中,当iOS应用程序连接到我在笔记本电脑上运行的Web服务时,我没有设置https。

从今天早上的一些实验中可以看出,URL加载系统即使你提供了http URL,也会决定使用https。有人知道如何禁用此行为-即使只针对特定的URL吗?


请查看此链接:https://dev59.com/o10Z5IYBdhLWcg3wnBb_?noredirect=1#comment52543453_31254725 - Jeef
我刚刚写了一篇指南,介绍如何验证您的Webservice以实现App传输安全。这可能会有所帮助。https://medium.com/@Mrugraj/app-transport-security-b7910c4fc70f - Mrug
不支持iOS 9.3 - nickalchemist
我注意到了一件事,这个问题是在6月9日被提出的,但是使它成为“重复”的链接是在7月6日... - 0yeoj
如何在NSExceptionDomains中指定IPAddress而不是域名? - Code Runner
8个回答

732

请查看苹果的Info.plist参考文档以获取完整细节(感谢@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会议703,“隐私和您的应用程序”,30:18)

如果您的应用程序有充分理由这样做,您还可以使用单个键忽略所有应用程序传输安全限制:

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

如果您的应用程序没有充分的理由,使用 NSAllowsArbitraryLoads 标志可能会导致被拒绝:

将 NSAllowsArbitraryLoads 设置为 True 可以让应用程序正常工作,但是苹果公司非常清楚地表示他们打算拒绝使用此标志的应用程序,除非有特定的原因。我能想到使用 NSAllowsArbitraryLoads 的主要原因可能是用户创建的内容(链接共享、自定义 Web 浏览器等)。即使在这种情况下,苹果仍然希望您包括强制 ATS 的例外情况,以针对您控制的 URL。

如果确实需要访问未通过 TLS 1.2 服务的特定 URL,则需要编写针对这些域名的特定例外条件,而不是使用 NSAllowsArbitraryLoads 设置为 Yes。您可以在 NSURLSesssion WWDC 会话中找到更多信息。

请注意谨慎在分享 NSAllowsArbitraryLoads 解决方案时。这不是苹果推荐的修复方法。

kcharwood(感谢 @marco-tolman)


5
请注意,CFNetwork.framework在beta 1中使用的大多数键与会话中呈现的字符串不同: NSTemporaryExceptionAllowsInsecureHTTPLoadsNSTemporaryExceptionMinimumTLSVersionNSTemporaryExceptionRequiresForwardSecrecyNSTemporaryThirdPartyExceptionAllowsInsecureHTTPLoadsNSTemporaryThirdPartyExceptionMinimumTLSVersionNSTemporaryThirdPartyExceptionRequiresForwardSecrecy - adurdin
2
现在有一份技术笔记发布在https://developer.apple.com/library/prerelease/ios/technotes/App-Transport-Security-Technote/index.html。 - gnasher729
11
有效的做法是将NSIncludesSubdomainsNSTemporaryExceptionAllowsInsecureHTTPLoads设置为<true /> - Cœur
28
这个回答中的信息对我没有用。 - Jonny
2
这个在2016年12月之后将不再适用于iOS 10。您的应用程序在info.plist中不能有这些键,否则您的应用程序将被App Store拒绝。 - Abuzar Amin
显示剩余10条评论

114

既然采纳的答案提供了所需信息,关于使用和禁用应用程序传输安全性的更多信息,可以在此处找到。

对于每个域名的异常情况,请将以下内容添加到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>

点击此链接获取更多细节信息。


提供简单设置示例的最佳答案。 - KoCMoHaBTa
14
仅使用IP地址无法运行。有人能帮我排除IP地址而不是域名吗? - HelmiB
4
请注意,输入域名时不需要在开头加上"http://"。 - Matias Elorriaga
1
这个在2016年12月之后将不再适用于iOS 10。您的应用程序在info.plist中不能有这些键,否则您的应用程序将被App Store拒绝。 - Abuzar Amin
在@AtWork中,您仍然可以在应用传输安全设置中添加例外域名,但必须有充分的理由,否则App Store将拒绝您的应用程序。如果您有企业应用程序,则完全不必担心这个问题。 - Abuzar Amin
显示剩余5条评论

61

参照此链接进行操作。

我通过在info.plist文件中添加一些关键信息来解决问题。我按照以下步骤进行:

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

  2. 添加一个名为NSAppTransportSecurity的关键信息,其类型为Dictionary

  3. 添加一个名为NSAllowsArbitraryLoads的子关键信息,其类型为Boolean,并将其值设置为YES,如下图所示。 enter image description here

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

参考链接


2
这在测试应用程序时非常有帮助,特别是当 SSL 证书不可用时。 - Ripwinder
4
从2016年12月开始,这将不再适用于iOS 10。你的应用程序在info.plist中不得具有这些密钥,否则你的应用程序将被App Store拒绝。 - Abuzar Amin

38
如果您只想在本地开发服务器上禁用App Transport Policy,则以下解决方案效果很好。当您无法或不实际设置HTTPS时(例如使用Google App Engine dev服务器时),这非常有用。
但是,正如其他人所说,生产应用程序绝对不应该关闭ATP。
1)为Debug使用不同的plist
复制您的Plist文件和NSAllowsArbitraryLoads。将此Plist用于调试。 XCode Debug
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

2)排除本地服务器

或者,您可以使用一个plist文件并排除特定的服务器。然而,似乎无法排除IPv4地址,因此您可能需要使用服务器名称(在系统偏好设置->共享中找到,或在本地DNS中配置)。

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

1
我强烈建议不要选择选项1,因为它可能会隐藏问题,在生产应用程序中会给你带来麻烦(例如,如果你正在使用第三方非安全域)。 - Ned
3
我感激你的反馈,但就我个人而言,我并不认为那应该被点踩。我并不是在说这是推荐的解决方案,我只是提供了另一种选择。显然,如果HTTP不可用,我会建议排除特定的域名,但kcharwood已经给出了那个答案。无论如何,我将把决定留给你。我只是想说明我的理由。 - Ian
1
明白了。这似乎是初学者可能会搜索的问题,看到允许任意加载的建议,并在没有考虑任何后果的情况下进行操作。通过允许任意加载来解决任何应用程序发布的问题,由苹果来拒绝该应用程序。为不同的构建配置设置不同的设置可能会导致某人在开发过程中使应用程序正常工作,但存档的构建可能会出现故障。我无法取消我的投票,但如果您编辑答案并提供一些选项1的潜在缺陷,我将很乐意取消投票。 - Ned

31

我已经解决了一个plist文件。

  1. 添加NSAppTransportSecurity字典。
  2. 添加名为“NSAllowsArbitraryLoads”的子键,值为布尔型:YES。

图片描述


1
自2016年12月之后,这在iOS 10中将不再起作用。您的应用程序在info.plist文件中不能含有这些键,否则您的应用程序将被App Store拒绝。 - Abuzar Amin
那么从iOS 10开始我们应该怎么做呢? - N Kaushik
@AbuzarAmin,你在哪里读到这个的?我正在我的一个应用程序中使用相同的方法,而且该应用程序运行良好。在iOS 10及以上版本中实现这一点的替代方法是什么? - Suryakant Sharma
@Suryakant,这是在WWDC视频中宣布的。如果您的应用程序已经在App Store上,那么当您提交应用程序进行审核时会出现问题。 - Abuzar Amin
@AbuzarAmin 但是除非你的应用程序有使用那个密钥的强烈理由,否则我在某处读到。 - Suryakant Sharma
显示剩余2条评论

23

对我来说,上述配置并没有起作用。我尝试了很多键的组合,但只有这个有效:

输入图像描述

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

这对我在Appcelerator 4.0.0.GA和xcode7上也起作用。 - Sam Texas
5
我正在尝试让我的应用程序向本地的Rails服务器发送HTTP请求,地址为localhost:3000...那么我应该填什么域名呢?我已经尝试过"localhost"、"localhost:3000"、http://localhost:3000等等,你有什么想法吗?提前感谢你的帮助! - OOProg
@OOProg 本地主机:3000 - Damien Romito
1
@OOProg - 对我而言,只是普通的localhost就可以工作了。另外,你需要确保你的请求URL是“http://localhost:3000”。如果NSURLSession数据任务没有前缀“http://”,则无法连接到localhost:3000。 - kcstricks
1
此代码将在2016年12月后的iOS 10中停止使用。您的应用程序在info.plist中不得具有这些键,否则您的应用程序将被App Store拒绝。 - Abuzar Amin

18

根据@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 必须像这样:

输入图像描述


"localhost" 还是 "localhost.com"? - pbreitenbach
本地主机必须正常工作,幸运的是localhost.com也可以工作,谢谢提醒,但请尝试localhost。 - Aqib Mumtaz
2
这个在2016年12月之后将不再适用于iOS 10。您的应用程序在info.plist中不能有这些键,否则您的应用程序将被App Store拒绝。 - Abuzar Amin
请问能否分享链接? - Aqib Mumtaz
看起来数值是错误的,在大多数其他答案中,至少AllowsInsecureHTTP被设置为true。 - Efren

16

这是对我起作用的方法:

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

希望这对你有所帮助。祝好!:)


2
这是允许异常域的首选方式,而不是使其对所有人开放(即通过将任意加载设置为“是”)。 - Jayprakash Dubey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接