JavaWeb服务:WS-Security的大开销

WS-Security 以现有的密码学以及 XML 加密和签名行业标准为基础,为 Web 服务应用程序提供了一组全面的安全特性,您可以通过 WS-Policy 和 WS-SecurityPolicy 来指定特定应用程序可以使用哪些特性,从而允许服务客户机自行配置以访问服务。通过跨多个平台和 Web 服务框架对这些标准的广泛支持,可以实现出色的互操作性(并且会不断改善)。

尽管能带来这么多好处,但 WS-Security 也存在一些缺点。在本 系列 的前两篇文章中,您已经知道 WS-Security 的配置有时会非常复杂,并且有时会在交换的消息中添加许多块(bulk)。那么,WS-Security 带来的收益在什么情况下才物有所值呢?在本文中,我们将深入探讨 WS-Security 以及相关 WS-SecureConversation 的运行时成本(在处理开销和添加块方面),并引申到如何应用 WS-Security 才能让应用程序受益的话题。

观察性能

为了测量应用程序在不同配置下的性能,本文将测定当客户机和服务器运行于同一系统中特定请求序列的执行时间。这种方法存在一些缺点 — 最显著的是,它将客户机和服务器处理开销结合在一起,因此不能单独测算它们 — 但它比在网络上运行测试能生成更加一致的结果。您还可以轻松地在自己的硬件和 JVM 上试运行这些测试,相关的实现代码请参见 下载。

性能测试应用程序

用于测试的应用程序是一个地震数据检索服务。它基于一个地震数据库,其中包含一段时间内世界各地发生的 93,000 多次地震的实际数据。对服务的请求将指定经度、纬度、日期或震级的范围,并且服务将按地区和时间顺序分组返回所有匹配的地震。整个数据库按索引保存在内存中,以便于快速处理请求,因此每条请求几乎所有的处理时间都花在实际的 Web 服务处理代码上(包括将转换为 XML 或从 XML 转换而来的数据绑定代码)。

清单 1 展示了一个对服务的示例请求,以及随后的响应(为适应页面宽度重新调整了格式):

清单 1. 示例请求和响应

         2001-08-08T16:31:05.752+00:00    2001-08-14T23:51:31.499+00:00    160.4685    178.19693    -42.423557    -30.44976                   New Zealand Region           NORTH ISLAND,        NEW ZEALAND      OFF E. COAST OF N. ISLAND,        N.Z.                                                                             

在测试中,客户机将查询范围调整为整体地震数据集的一部分,并生成一系列伪随机请求。每次使用相同输入参数运行客户机所生成的请求序列都是相同的,这允许我们测试不同的 Web 服务配置。通过更改客户机的输入参数(用于更改请求所使用的查询范围),可以轻松地测试不同的结果消息大小。

WS-Security 性能

本文所示的测试结果基于两个请求序列。第一个序列使用 1,000 条请求,查询参数经过调整以便各查询只匹配整个地震数据库的一小部分(1,000 条请求仅返回 826 次匹配的地震)。第二个序列使用 100 条请求,同时调整以匹配更大的数据库部分(100 条请求返回 176,745 次匹配的地震)。每个请求序列都在不同的安全性配置下运行了多次,每种配置只取最好的测试结果。

运行测试的环境是 Mandriva 2009.1 64-bit Linux® 系统、Athlon X2 5400+ 处理器、4GB 内存和 Sun Java 1.6.0_13 32 位 JVM。服务器代码在 Tomcat 6.0.20 上运行,配置为使用 1,024MB 大小的堆,客户机代码使用 512MB 大小的堆。我们使用 1.5 版本的 Axis2,并使用最新版本的 Rampart 代码。(在本文测试时,还没有与 Axis2 1.5 代码相匹配的 Rampart 发行版可用。要运行完整的测试集,为 Tomcat 配置 1,024MB 大小的堆是非常必要的(为各安全性配置使用单独的 Web 服务应用程序);刚开始使用 256MB 大小的堆执行测试时,WS-Security 测试有时会因为各种奇怪的错误(举例来说,未提供 DTD 时出现的 “SOAP message MUST NOT contain a Document Type Declaration(DTD)” 错误)或者 java.lang.OutOfMemoryError 而失败。

我们使用以下安全性配置运行各测试:

plain:无安全性

ssl:使用 HTTPS 连接到服务器

username:请求中使用 WS-Security 纯文本 UsernameToken

sign:WS-Security 主体和报头签名,使用时间戳

encr:WS-Security 主体加密

signencr:WS-Security 主体和报头签名,使用时间戳和主体加密

实际测试时间从 plain 配置的 4 秒到 signencr 配置的 55 秒。图 1 显示了相对测试时间,为便于比较使用了相对 plain 配置时间的倍数:

图 1. 测试时间比较

从 图 1 中可以看出,Secure Sockets Layer (SSL) — 从技术上说,现在应该称作 Transport Layer Security (TLS),但本文仍然使用为人所熟知的旧表示方法 — 加密所提供的性能接近无保护措施时的性能水平(但其处理大消息比处理小消息的性能要好,处理小消息所花的时间要长 80%,处理大消息所花的时间要长 20%)。另一方面,使用 WS-Security 会造成性能显著降低。仅在请求消息上添加简单的 UsernameToken 报头会造成性能降低到 SSL 处理小消息时的性能水平,但比使用 SLL 处理大消息时的性能慢 几倍。在签名与加密相结合的情况下,测试时间比无保护措施下要长 2,100%。

从一定程序上说,WS-Security 带来的这种性能上的影响归因于 Rampart 处理程序实现的缺陷,这会造成每次有 Rampart 参与时都将各请求和响应消息转换成 Document Object Model (DOM) 格式(即使未对消息执行任何安全性处理)。应该在 Rampart 1.5 发行版中修复此问题以便它可以兼容 Axis2 1.5。根据修复的实现方式,它可以显著改善 UsernameToken 测试的运行时间。但是,即使修复了此问题可能也不会影响其他的 WS-Security 运行时间。

与 WS-Security 相结合的 XML Signature 和 XML Encryption 的运行方式,以及 WS-Security 和这些 XML 标准的实现所使用的库也是影响性能的因素之一。还记得 “Java Web 服务:Axis2 WS-Security 签名和加密” 这篇文章说过,签名 XML 消息需要一个叫做规范化 的步骤,用于在捕获签名值之前将 XML 转换为特定的规范格式。标准需要这一步骤是因为已经确定即使在解析器分解 XML 并重新生成它之后也需要保留签名。虽然这毫无疑问是 XML Signature 的一个实用的特性,但它为处理增加了大量的开销。在一定程度上,由于使用 DOM 模型是实现规范化最简单的一种方法,因此 XML 安全性库都被设计为操作 XML 的 DOM 表示。(这是为何 Rampart 处理程序即使在参与服务或客户机任务时也要生成 DOM 的原因,但前提是 DOM 有必要的作用)。仅将数据转换成 DOM 表示的步骤就会造成大量的 WS-Security 开销,这可以从 UsernameToken 时间看出。在大响应消息的情况中,这种开销看上去与实际的签名或加密处理相当(如 图 1 所示,比较 username 测试的红柱 — 其中,唯一的主要开销是 DOM 的创建 — 与 sign 和 encr 测试的红柱,其中,实际的加密处理是在创建 DOM 之后完成的)。

除了 DOM 问题之外,大部分 WS-Security 开销都是计算紧密型的生成摘要和加密数据的任务。这一部分的工作是必需的,而与所使用的实现方法无关,因此 WS-Security 处理时间的改善是有限的。本系列的后续文章将比较其他一些使用 Axis2/Rampart 的 WS-Security 实现的性能 — 但是,它们大多数都使用相同底层库,因此不要指望能看到巨大的差异。

WS-SecureConversation

WS-SecureConversation 是在 WS-Security 和 WS-Trust 标准之上构建的一种标准,用于支持涉及多个消息的安全交换。由于它所使用的上下文针对运行中的消息交换,因此 WS-SecureConversation 更有可能比 WS-Security 实现更高的效率。Rampart 发行版包括一个单独的 rahas 模块,它支持发起 WS-SecureConversation 所需的安全令牌。它还包括一个使用 WS-SecureConversation 的策略配置示例(samples/policy/sample04),用于作为性能测试应用程序所使用的策略基础。

WS-SecureConversation 策略(未包含在此处,请参见 下载 中的 secureconversation-policy-client.xml)包括一个 元素,用于描述消息交换将使用的安全令牌,以及提供应用于 token-exchange 消息的安全性选项。这些 token-exchange 消息使用由 rahas 模块实现的操作为客户机和服务之间的消息交换提供支持 — 因此在使用 WS-SecureConversation 时,您偶尔会看到 request-response 消息对在客户机和服务器之间传递,如 清单 2 所示。要区分添加的这些 token-exchange 消息与应用程序消息,可以根据它们所使用的不同的安全性选项(由策略定义),以及它们所使用的特殊的 http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT 请求和 http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT 响应操作代码(两者都由 WS-SecureConversation 定义)。

清单 2. 示例请求和响应

         ...      http://localhost:8800/axis2/services/seismic-secureconversation       http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anOnymous      urn:uuid:5EA8E8F04EBA73255B1246409570148   http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT           ...              ...      http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anOnymous   urn:uuid:1BCDE6BE423F5FDE791246409571325   http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT   urn:uuid:5EA8E8F04EBA73255B1246409570148           ...    

为了与普通的使用证书的 WS-Security 的性能相比较,WS-SecureConversation 配置被设置为仅在加密消息主体时使用会话令牌。图 2 展示了最终测试时间与 plain 及 encr 测试配置之间的比较,为便于比较使用了相对 plain 配置时间的倍数:

图 2. WS-SecureConversation 时间比较

如 图 2 所示,WS-SecureConversation 加密确实相对 WS-Security 提供显著的性能改善。这对于较小的消息尤为明显,其 WS-SecureConversation 配置的运行速度几乎是使用证书的 WS-Security 加密的两倍。而对于较大的消息来说,性能优势则逊色许多,但 WS-SecureConversation 仍然提供了 18% 的速度提升。

消息大小比较

从系列的前一篇文章中看到,WS-Security 可以会向 SOAP 消息报头添加大量块(bulk)。当数据通过网络在客户机与服务器之间传递时,这些添加的块会对性能造成显著影响(而在本文中,客户机和服务器是在相同的系统上运行的)。客户机与服务之间的网络连接的质量将决定这些增加的块会对性能造成多大的影响,但毫无疑问的是,消息越大,交换速度就越慢。

图 3 显示了不同测试用例中的典型消息的实际大小,为便于比较使用了相对 plain 配置时间的倍数:

图 3. 消息大小比较

与预期相符,username 配置仅增加了请求消息的大小,因为 UsernameToken 仅出现在请求消息中。其他安全性配置则同时增加了请求和响应消息的大小。WS-Security 添加的块对于较小的请求和响应消息来说更加明显。对于各配置来说,WS-Security 报头基本上是恒定不变的,因此当原始消息大小较小时,相同大小的增加会带来更加显著的影响。在使用加密时,加密数据所使用的 base64 编码中出现了单独的填充(padding)效果。

何时使用 WS-Security

您已经了解了 WS-Security 对处理时间和消息大小的影响。您可能想知道这些代价何时才是值得的。简单的回答是:当较简单的 SSL 替代方案没有作用时。在本节的其余部分,我们将提供一些指导方针来帮助您确定 SSL 是否能满足您的需求,或者是否需要全功能的 WS-Security 解决方案,并且还将指导您在选择 使用 WS-Security 后最大限度降低与之相关的开销。

保密

保护机密信息是安全性最重要的一个方面。WS-Security 使用 XML Encryption 保护消息内容不被非目标接收者获取,其方法通常是使用封装在数字证书中的公共密匙。加密可以应用于整个消息或所选部分,并且您甚至可以使用多层加密来控制哪些信息可以由涉及多个系统的消息交换中的参与者访问。

WS-Security 的一个示例用例是一个在线购物系统,其中,客户机连接到商业系统下订单,但付款(比如说,通过信用卡)需要在处理订单前由某银行系统确认。如果商业系统能够以未加密的形式访问信息卡信息,则会带来基于浏览器的购物网站所特有的安全性风险:信用卡最终经常会存储在安全性较差、易于受到黑客攻击的数据库中。使用 WS-Security,信用卡信息可以以加密的格式传递,并且仅能由发出付款确认的银行系统解密。

但是,对于许多应用程序来说,在保护机密信息方面,WS-Security 和 XML Encryption 的功能有点过于强大。如果您的服务需要客户直接与之联系(而不是间接通过其他服务器)并且直接执行所有必要的处理,那么您可以仅使用 SSL (HTTPS) 连接来实现访问功能,这样能以比 WS-Security 更低的成本提供出色的机密信息保障功能。不过,这种方法仅适用于直接客户机连接。否则,如果服务需要将信息传递给其他服务,那么您又遇到了与在线购物网站易受攻击的情况:您使用安全的连接向购物网站传递信用卡信息,但是却无法保证信息将安全地保存在站点服务器上。

维持数据完整性

数据完整性是与机密性相类似的一个问题。WS-Security 使用 XML Signature 确保数据不会在传输中被篡改,因为任何窜改都会导致签名失效。与 XML Encryption 相同,签名可以应用于整个消息或者所选部分,并且您可以使用多层签名来保证涉及多个系统的消息交换中的参与者所处理的数据的完整性。

虚构的在线购物系统还提供了很好的数据完整性的例子。使用 WS-Security,客户对发送给银行系统的付款指令进行签名,从而防止中间的商业系统随意修改指定的付款额。由于付款额经过客户签名,因此不需要对它进行加密,以便商业系统在向银行系统提交事务之前确定付款额正确无误。

此处,如果您的服务需要客户直接与之连接并且在内部执行所需必需的处理,则 WS-Security 和 XML Signature 又显得有些过于强大了。SLL 连接不仅能保证数据的机密性,它们还能防止数据在传输过程中被修改 — 但仅限于在在单一的客户机与服务器之间。如果服务器将数据传递给其他系统,则这些系统无法保证数据不被服务器修改。

确保真实性

在真实性方面,WS-Security 所提供的特性是 SLL 所无法匹及的,即使针对客户机与服务器之间的直接连接。使用 WS-Security 和 XML Signature 对消息进行签名,不仅允许您的文档在接收和处理时进行真实性验证,还可以为用于审计的文档提供可靠的真实性保障。

SSL 在这方面做的出色的地方就是在客户机与服务器之间建立连接时要求客户机证书作为身份证明。但是,它所提供的真实性保障要比消息数字签名弱很多。您不能轻易地将客户机与服务器之间交换的整个数据流保存为 SSL 连接的一部分,因此,即使您在建立该连接时验证了客户机证书,也无法在稍后返回并证明此步骤已得到正确处理。

再次回到在线购物系统示例,付款指令上的客户机签名将允许该指令由银行系统保存,并在以后就该事务出现任何争辩时提供该签名。这样,银行系统便可以证明 付款已经得到了客户的授权,从而让自己免除任何责任。

其他特性

除了基本的机密性、完整性和真实性之外,WS-Security 还针对特定的安全性需求提供了许多其他特性。举例来说,UsernameToken 就是一个简单的特性,它提供了与服务传递基本用户授权的标准方法。其他 WS-Security 特性还允许 Security Assertion Markup Language (SAML) 授权令牌和其他形式的与安全性相关的信息,用于添加到 SOAP 消息交换中。如果需要在 Web 服务中使用此类型的安全性信息,可以使用 WS-Security 支持来传递信息,因为它定义了一些标准的格式和过程,可能会比您自己实现的功能更加可靠。

降低 WS-Security 的成本

如果您要使用 WS-Security,可以从本文的测试结果中看出性能是一个问题。但是,在顾虑其开销之前,请考虑一下您服务的数据量。使用 WS-Security 进行加密和签名之后,服务的性能会大打折扣 — 但是,如果您的服务每小时只交换少量消息,则硬件需求方面的差异是可以忽略不计的。

对于性能无法折衷的场景,您可以通过合理地安全性选项来帮助最大限度地减小性能影响。某些 Web 服务框架倾向于生成 “所有上述” 安全性配置,它们使用 WS-Security 实现全面的消息签名和加密,并 通过 SSL 连接发送它们。如果您确实希望提供最高级别的保护,而对性能毫不关心,那么这种方式没有问题。但是,在大多数情况下,更有意义的方法是使用 SSL(如果只关心为在客户机和单一服务器之间传输的信息提供保护)或者 WS-Security 加密(如果需要跨多个服务器传递数据,同时在它们经过中间系统时保护机密信息的安全。

对于客户机和服务器之间需要长时间交换消息的情况工(甚至通过中间系统访问其一),您还可以使用 WS-SecureConversation 提供相对于使用证书的 WS-Security 更好的性能。WS-SecureConversation 特别适合相对较小的消息之间的交换,其中,证书和非对称加密方面增加的开销与消息主体的实际(对称)加密相比是相当可观的。

降低 WS-Security 性能成本的另一种方法是将安全性处理转嫁给专门的硬件来完成。一些 XML 网关工具提供了对 WS-Security 加密和签名的加速处理。您可以使用这些工具来处理大开销的 WS-Security,同时处理应用程序中的纯 SOAP。显然,您需要确保在向服务器添加工具时不会打开任何潜在的安全性漏洞。并且,您应该在购买之前测试工具所带来的性能提升。但是,至少从理论上来说,这种模式确实能实现一些性能提升。

结束语

WS-Security 的性能成本是可观的,并且简单的 SSL 点对点加密有时是更好的解决方案。但是,对许多应用程序而言,SSL 是远远不够的。在这些情况中,就必须使用 WS-Security(或者它的后代 WS-SecureConversation),而且性能成本也成为必要的开销。在本文中,您已经了解了 WS-Security 的成本,并学习了一些可帮助您确定 WS-Security 是否适用于自己应用程序的指导方针。

在本系列的下一篇文章中,我们将从另一个视角来解读 WS-Security,将演示如何使用 WS-SecurityPolicy 实现对 Web 服务中各操作所使用的 WS-Security 特性的粒度化控制。在操作层面控制 WS-Security 也是一个能够(至少可能)降低 WS-Security 开销的技巧,因此,在转向其他话题之前,这是对本文的最好的沿续。

文章来源:

http://www.ibm.com/developerworks/cn/java/j-jws6/

所以你不懂我的选择,也可以不懂我的难过,

JavaWeb服务:WS-Security的大开销

相关文章:

你感兴趣的文章:

标签云: