如何使用NSURLConnection取消持久连接? [英] How to cancel a persistent connection using NSURLConnection?

查看:266
本文介绍了如何使用NSURLConnection取消持久连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Is it possible to destroy a persistent connection that has been created with NSURLConnection? I need to be able to destroy the persistent connection and do another SSL handshake.

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

As it is now, calling [conn cancel] leaves a persistent connection behind that gets used with the next connection request to that host, which I don't want to happen.

推荐答案

事实证明,我相信安全传输TLS会话缓存应该受到责备。

As it turns out, I believe the Secure Transport TLS session cache is to blame.

我还问了一个问题,得到了苹果公司的回复。他向我指出了这个 Apple示例代码自述文件,其中包含:

I also asked the question on the apple developer forums, and got a response from an Apple person. He pointed me to this Apple sample code readme where it says:


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

At the bottom of the TLS stack on both iOS and Mac OS X is a component known as Secure Transport. Secure Transport maintains a per-process TLS session cache. When you connect via TLS, the cache stores information about the TLS negotiation so that subsequent connections can connect more quickly. The on-the-wire mechanism is described at the link below.

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

这会带来一些有趣的问题,特别是当你'重新调试。例如,请考虑以下序列:

This presents some interesting gotchas, especially while you're debugging. For example, consider the following sequence:


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

  1. You use the Debug tab to set the TLS Server Validation to Disabled.

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

You connect to a site with a self-signed identity. The connection succeeds because you've disabled TLS server trust validation. This adds an entry to the Secure Transport TLS session cache.

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

You use the Debug tab to set the TLS Server Validation to Default.

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

You immediately connect to the same site as you did in step 2. This should fail, because of the change in server trust validation policy, but it succeeds because you never receive an NSURLAuthenticationMethodServerTrust challenge. Under the covers, Secure Transport has resumed the TLS session, which means that the challenge never bubbles up to your level.

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

On the other hand, if you delay for 11 minutes between steps 3 and 4, things work as expected (well, fail as expected :-). This is because Secure Transport's TLS session cache has a timeout of 10 minutes.

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

In the real world this isn't a huge problem, but it can be very confusing during debugging. There's no programmatic way to clear the Secure Transport TLS session cache but, as the cache is per-process, you can avoid this problem during debugging by simply quitting and relaunching your application. Remember that, starting with iOS 4, pressing the Home button does not necessarily quit your application. Instead, you should use quit the application from the recent applications list.

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

So, based on that, a user would have to either kill their app and restart it or wait more than 10 minutes before sending another request.

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

I did another google search with this new information and found this Apple technical Q&A article that matches this problem exactly. Near the bottom, it mentions adding a trailing '.' to domain names (and hopefully IP addresses) for requests in order to force a TLS session cache miss (if you can't modify the server in some way, which I can't), so I am going to try this and hopefully it will work. I will post my findings after I test it.

###编辑###

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

I tested adding a '.' to the end of the ip address, and the request was still completed successfully.

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

But I was thinking about the problem in general, and there's really no reason to force another SSL handshake. In my case, the solution to this problem is to keep a copy of the last known SecCertificateRef that was returned from the server. When making another request to the server, if a cached TLS session is used (connection:didReceiveAuthenticationChallenge: was not called), we know that the saved SecCertificateRef is still valid. If connection:didReceiveAuthenticationChallenge: is called, we can get the new SecCertificateRef at that time.

这篇关于如何使用NSURLConnection取消持久连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆