我已向 iOS 团队写了一份支持请求。这是他们回答的内容...实际上它与htpps有关...以防万一有人遇到相同的错误,这可能是原因:
我正在回答您关于为什么您的 SOAP 请求在 iOS 7 上失败的问题,但仅限于针对您的两台服务器之一时。你写了:
可能与一台服务器在 https 上运行而另一台在 http 上运行这一事实有关吗?
事实证明,你的理论是正确的。这里的问题是 iOS 7 包含了针对 BEAST 攻击的推荐对策。
http://en.wikipedia.org/wiki/Transport_Layer_Security#BEAST_attack
http://www.educationguesswork.org/2011/11/rizzoduong_beast_countermeasur.html
https://www.imperialviolet.org/2012/01/15/beastfollowup.html
iOS 在与协商使用块密码(流密码不易受到此攻击)的 TLS 1.0 或更早版本的服务器(TLS 1.1 及更高版本包含他们自己的针对此攻击的修复)通信时应用此对策。
查看您发送给我的测试应用程序的数据包跟踪,我可以看到它打开了与 www.xxxx.xy:443 的 TLS 1.2 连接。该服务器将连接降级到 TLS 1.0,然后协商使用 AES-128 块密码 (SSL_RSA_WITH_AES_128_CBC_SHA)。在那之后,我可以看到这种反制措施的明显迹象。
我通过在模拟器上运行您的测试应用程序(它准确地重现了问题)来确认我的分析,然后使用调试器设置安全传输(在 iOS 上实现 TLS 的子系统)的内部状态以完全禁用此对策。在这样做时,我发现您应用程序中的第一个选项卡工作正常。
这种对策的一个众所周知的副作用是它会导致编写不佳的 HTTPS 服务器出现问题。这是因为它将 HTTP 请求(通过 TLS 连接运行的请求)分解成块,并且服务器必须经过编码才能正确接收这些块并将它们加入单个 HTTP 请求。一些服务器不能正确地做到这一点,这会导致各种有趣的故障。
解决此问题的最佳方法是修复服务器。服务器应该能够处理以块的形式接收 HTTP 消息,以 RFC 2616 规定的方式检测 HTTP 消息边界。
http://www.ietf.org/rfc/rfc2616.txt
如果该修复在短期内难以实施,您可以通过简单地升级您的服务器以支持 TLS 1.2 来解决该问题。无论如何,这是个好主意。
另一种解决方法,一个不太好的主意,是调整服务器配置以协商流密码的使用。
如果您不控制服务器,我强烈建议您游说服务器运营商为该问题提供服务器端修复。iOS 7 不是唯一实现此变通方法的客户端;您会在 Chrome、Firefox 等的最新版本中找到它。
如果无法进行服务器端修复,那么您在客户端的选择就不太理想:
o 您可以将 HTTPS 替换为 HTTP。显然这不是一件好事,而且还需要服务器支持HTTP。此外,HTTP 也有它自己的一系列不有趣的问题(各种中间盒,尤其是那些由蜂窝运营商运行的中间盒,喜欢胡乱处理 HTTP 消息)。
o 在最低级别,您可以通过 kSSLSessionOptionSendOneByteRecord 标志为给定的安全传输上下文禁用此对策(请参阅 参考资料)。虽然可以在 CFSocketStream 层使用此标志,但高级软件不能直接使用此标志(因为该 API 为您提供了一种获取它正在使用的安全传输上下文的方法)。
重要提示:高级 API,NSURLSession 和 NSURLConnection,不让你访问安全传输上下文,也不提供对 TLS 的这方面的任何控制。因此,无法禁用此对策并继续使用那些漂亮的高级 API。
o 您可以在我们的 TLS 基础设施(最好是 CFSocketStream)之上实现自己的 HTTP 层。唉,这是一个痛苦的世界:HTTP 比你想象的要复杂得多。
很抱歉我没有更好的消息。