如何使用NSURLConnection取消持久连接?

时间:2012-11-13 21:46:17

标签: iphone objective-c ios ssl nsurlconnection

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

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

3 个答案:

答案 0 :(得分:17)

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

我还问了on the apple developer forums这个问题,得到了一个苹果人的回复。他向我指出了Apple sample code readme所说的内容:

  

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

     

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

     

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

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

  2.   
  3. 您连接到具有自签名身份的网站。连接成功,因为您已禁用TLS服务器信任验证。这会在Secure Transport TLS会话缓存中添加一个条目。

  4.   
  5. 使用“调试”选项卡将TLS服务器验证设置为默认值。

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

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

  10.         

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

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

我使用这些新信息进行了另一次谷歌搜索,发现this Apple technical Q&A article完全匹配此问题。在底部附近,它提到添加尾随'。'为了强制TLS会话缓存未命中(如果你不能以某种方式修改服务器,我不能),请求域名(并希望IP地址),所以我将尝试这个,希望它将工作。我会在测试后发布我的发现。

###编辑###

我测试了添加'。'到IP地址的末尾,请求仍然成功完成。

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

答案 1 :(得分:0)

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

答案 2 :(得分:-3)

首先,你应该使用     [self.conn取消] 第二,这就是它所说的。它取消了自己。如果您不想再使用NSURLConnection,它将不会执行任何操作,如果您再次使用它,您可以设置一个不同的请求,它将连接到给定的服务器。

希望有所帮助。