1

我有一个通过 SOAP 请求获取数据的 iPhone 应用程序。SOAP 调用由 sudzc.com 库完成。

我必须向两台服务器发出 SOAP 请求。

  • Server A : 是我自己的服务器,我在这里检索一些信息,我自己写的 SOAP Response
  • 服务器 B : 一个第三方服务器,它给我一些必要的信息

iOS 6 应用程序 100% 正确运行。

IOS 7

  • 服务器 A:完美运行
  • 服务器 B:SOAP 请求随机失败。我有时会收到以下错误消息:

    < SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> < SOAP-ENV:Header/> < SOAP-ENV:Body> < SOAP-ENV:Fault > < faultcode>SOAP-ENV:Server < faultstring xml:lang="en">无法访问信封:无法从给定源创建信封:;嵌套异常是 com.sun.xml.internal.messaging.saaj.SOAPExceptionImpl:无法从给定源创建信封::无法从给定源创建信封::org.xml.sax.SAXParseException:文档中的标记在根元素必须格式正确。:文档中根元素之前的标记必须格式正确。</faultstring> <detail/> </SOAP-ENV:Fault> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

任何人都有一个想法,为什么这只发生在iOS7上以及我如何摆脱它?

更新: 这可能与一台服务器在 https 上运行而另一台在 http 上运行的事实有关吗?

4

1 回答 1

1

我已向 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 比你想象的要复杂得多。

很抱歉我没有更好的消息。

于 2013-10-11T09:02:31.877 回答