18

是否可以销毁使用 NSURLConnection 创建的持久连接?我需要能够破坏持久连接并进行另一次 SSL 握手。

就像现在一样,调用 [conn cancel] 会留下一个持久连接,用于该主机的下一个连接请求,我不希望发生这种情况。

4

3 回答 3

18

事实证明,我相信安全传输 TLS 会话缓存是罪魁祸首。

我也在苹果开发者论坛上问过这个问题,得到了苹果人的回复。他指给我看这个Apple 示例代码自述文件,上面写着:

iOS 和 Mac OS X 上 TLS 堆栈的底部是一个称为安全传输的组件。安全传输维护每个进程的 TLS 会话缓存。当您通过 TLS 连接时,缓存会存储有关 TLS 协商的信息,以便后续连接可以更快地连接。在线机制在下面的链接中进行了描述。

http://en.wikipedia.org/wiki/Transport_Layer_Security#Resumed_TLS_handshake

这提出了一些有趣的问题,尤其是在您进行调试时。例如,考虑以下序列:

  1. 您使用调试选项卡将 TLS 服务器验证设置为禁用。

  2. 您连接到具有自签名身份的站点。连接成功,因为您已禁用 TLS 服务器信任验证。这会向安全传输 TLS 会话缓存添加一个条目。

  3. 您使用调试选项卡将 TLS 服务器验证设置为默认值。

  4. 您立即连接到与步骤 2 中相同的站点。由于服务器信任验证策略的更改,这应该会失败,但它会成功,因为您从未收到 NSURLAuthenticationMethodServerTrust 质询。在幕后,安全传输已恢复 TLS 会话,这意味着挑战永远不会冒泡到您的水平。

  5. 另一方面,如果您在第 3 步和第 4 步之间延迟 11 分钟,事情会按预期工作(好吧,按预期失败 :-)。这是因为 Secure Transport 的 TLS 会话缓存有 10 分钟的超时。

在现实世界中,这不是一个大问题,但在调试过程中可能会非常混乱。没有编程方式来清除安全传输 TLS 会话缓存,但由于缓存是每个进程的,因此您可以在调试期间通过简单地退出并重新启动应用程序来避免此问题。请记住,从 iOS 4 开始,按下 Home 按钮并不一定会退出您的应用程序。相反,您应该使用从最近的应用程序列表中退出应用程序。

因此,基于此,用户必须要么杀死他们的应用程序并重新启动它,要么等待超过 10 分钟,然后再发送另一个请求。

我用这个新信息做了另一个谷歌搜索,发现这篇苹果技术问答文章与这个问题完全匹配。在底部附近,它提到添加尾随“。” 到请求的域名(希望是 IP 地址)以强制 TLS 会话缓存未命中(如果你不能以某种方式修改服务器,我不能),所以我将尝试这个并希望它将工作。我会在测试后发布我的发现。

### 编辑 ###

我测试了添加一个“。” 到ip地址的末尾,请求仍然成功完成。

但我一般都在考虑这个问题,真的没有理由强迫另一个 SSL 握手。就我而言,这个问题的解决方案是保留从服务器返回的最后一个已知的 SecCertificateRef 的副本。当向服务器发出另一个请求时,如果使用了缓存的 TLS 会话(connection:didReceiveAuthenticationChallenge:未调用),我们知道保存SecCertificateRef的仍然有效。如果connection:didReceiveAuthenticationChallenge:被调用,我们可以SecCertificateRef在那个时候得到新的。

于 2012-11-14T05:14:50.907 回答
0

从 OS X 10.9 开始,NSURLSession 是解决方案。

于 2016-06-06T06:34:23.453 回答
-3

首先,您应该使用 [self.conn cancel],其次,这正是它所说的。它会自行取消。如果你不想再使用 NSURLConnection ,它不会做任何事情,如果你再次使用它,你可以设置一个不同的请求,它将连接到给定的服务器。

希望有帮助。

于 2012-11-13T22:13:34.093 回答