您已经在Java Web服务系列中看到了许多WS-Policy和WS-SecurityPolicy的示例,但是到目前为止,还没有任何关于WS-Policy实际工作方式(或至少是打算工作)的讨论。 在本文中,我将首先通过为您提供有关WS-Policy的背景知识来填补空白。 然后,您将看到如何将策略附加到WSDL文档中的服务。 最后,我将尝试一些针对Axis2,Metro和CXF的WS-Policy配置示例,并告诉您它们在实践中如何工作。 (请参阅下载以获取完整的示例代码。)
WS-Policy定义了一个简单的XML结构,该结构由四个不同的元素和一对属性组成。 WS-Policy解释了这些元素和属性,提供了一种组织和组合任何复杂程度的策略声明的方法。 要定义构成策略的实际断言,请使用特定于域的扩展,例如WS-SecurityPolicy,而不是WS-Policy本身。
为方便起见,WS-Policy定义了策略的标准形式的表达式以及可用于创建更紧凑的策略表达式的一组规则。 普通格式可能有些冗长,因此(尽管WS-Policy建议指出“应在可行的情况下使用策略表达的普通形式”),大多数策略文档的作者倾向于至少使用紧凑表达式的某些部分使文档更人性化的规则。 不过,政策文件的解释是基于常规格式的,因此,我将首先介绍其内容。
范式策略表达式最多使用三个元素,这些元素必须始终以特定顺序嵌套。 最外面的元素始终是<wsp:Policy>
,并且必须包含单个<wsp:ExactlyOne>
子元素。 嵌套的<wsp:ExactlyOne>
依次包含任意数量(可能为零)的<wsp:All>
子元素。 因此,最简单的范式策略表达式是<wsp:Policy><wsp:ExactlyOne/></wsp:Policy>
。
常规形式的任何策略声明都必须嵌套在<wsp:All>
元素内。 这些策略断言本身可以包含策略表达式。 您在本系列的前几篇文章中已经看到了这一点,其中许多WS-SecurityPolicy断言都包含嵌套的策略表达式。 在标准格式的策略表达式中,所有这些嵌套的策略声明本身也必须为标准格式。 (实际上,它们必须属于常规形式的甚至更多的限制性子集,其中除最顶层的每个元素之外,每个<wsp:ExactlyOne>
元素都具有一个且只有一个<wsp:All>
子元素。)清单1显示了一个摘录,其中包含嵌套策略表达式的几个示例,以正常形式表示:
<wsp:Policy>
<wsp:ExactlyOne>
<wsp:All>
<sp:AsymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<wsp:ExactlyOne>
<wsp:All>
<sp:InitiatorToken>
<wsp:Policy>
<wsp:ExactlyOne>
<wsp:All>
<sp:X509Token
sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<wsp:ExactlyOne>
<wsp:All>
<sp:RequireThumbprintReference/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</sp:X509Token>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</sp:InitiatorToken>
...
尽管嵌套元素有很多层,但此结构的语义很简单。 在策略的标准格式表达式中, <wsp:Policy>
只是策略表达式的包装,对于顶级策略表达式,是将名称或标识符附加到策略的位置。 嵌套的<wsp:ExactlyOne>
元素表示由嵌套的<wsp:All>
元素表示的替代项或替代项的组合(因此,如果满足任何嵌套替代项,则将满足整个策略表达式)。 每个<wsp:All>
元素代表嵌套策略声明的和组合(这样,只有在所有声明都得到满足时,替代条件才被满足)。
策略表达式不必采用正常形式。 非常规策略表达式可以包括嵌套的替代项(顶层以下<wsp:ExactlyOne>
元素的多个<wsp:All>
子元素),并且还可以利用下一节中讨论的紧凑型策略表达式选项。
如果您学习过逻辑理论,则可能会认识到正规形式的表示形式(没有嵌套的替代方案)等同于逻辑表达式的析取正规形式。 策略表达式实际上只是使用尖括号格式(带有断言作为子句)的逻辑表达式。 逻辑理论表明,任何逻辑表达式都可以转换为析取范式,并且同一原则也适用于使用嵌套替代项编写的策略表达式-它们可以扩展为仅在顶层具有替代项的范式表示。 规范形式的策略表达的主要优点在于,它可以轻松地以编程方式检查两个策略的兼容性-如果两个规范形式的策略兼容,它们将具有一个或多个顶级<wsp:All>
包含相同断言集的元素。
策略的范式表达可能很长,尤其是当它涉及嵌套的替代方案时。 WS-Policy定义了一些选项,您可以使用这些选项来创建比常规形式所允许的更为简洁的策略表达式,从而使人们更容易理解这些策略。 WS-Policy文档有时会以紧凑形式引用使用这些选项的策略,从而造成混乱。 实际上,策略的许多紧凑表达式都可以等同于单个范式表达式。 在本文中,我将仅使用紧凑表达式来使用其中一个或多个选项来引用策略。
紧凑表达式选项的一个功能是能够通过以任何顺序嵌套基本策略元素(在策略术语中称为操作符 ,因为每个元素都暗含了对嵌套断言的特定解释)来表达策略。 嵌套规则还定义了对直接使用的<wsp:Policy>
元素的解释(没有常规形式所需的单个<wsp:ExactlyOne>
子元素),等同于<wsp:All>
,这可能是最广泛的使用紧凑表达式功能。
清单2使用此<wsp:Policy>
表示形式给出了清单1中所示策略的紧凑表达式。 此版本的长度不到第一个版本的一半,对于大多数人而言,它更容易理解。
<wsp:Policy>
<sp:AsymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireThumbprintReference/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
...
WS-Policy定义了一组转换,您可以应用这些转换来使用紧凑选项将策略表达式转换为普通格式,因此没有理由直接使用普通格式。 与将人类解释为正常形式相比,计算机将紧凑型表达形式转换为正常形式要容易得多。
除了简化元素嵌套之外,紧凑表达式还提供了一种引用和重用策略表达式的方法。 您可以使用第四个WS-Policy元素<wsp:PolicyReference>
。 <wsp:PolicyReference>
元素可以出现在可以出现策略断言的任何位置。 引用的策略表达式有效地替代了策略引用(技术上用<wsp:All>
元素替换了引用的<wsp:Policy>
元素)。 这种替代方法称为政策包含 。
清单3说明了策略包含的用法,显示了清单2策略表达式,使用单独的策略表达式和引用将其重构为表单:
<!-- Client X.509 token policy assertion. -->
<wsp:Policy wsu:Id="ClientX509"
xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd">
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token
sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireThumbprintReference/>
</wsp:Policy>
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
</wsp:Policy>
<wsp:Policy>
<sp:AsymmetricBinding
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<wsp:PolicyReference URI="#ClientX509"/>
...
策略引用既可以用于清单3所示的本地策略表达式,也可以用于外部策略表达式。 对于外部策略表达式,引用的URI
属性通常提供外部策略的实际URL。
正如您将在本文后面提供的策略测试示例中看到的那样,目前尚不普遍支持包含策略。 这限制了此本来不错的功能的实用性。
如您先前所见,WS-Policy的结构通过<wsp:ExactlyOne>
元素支持在替代方案中进行选择,作为策略的一部分。 使用紧凑表达式,您也可以(至少在理论上)使用特殊属性来创建选择。 根据WS-Policy建议,您可以将wsp:Optional="true"
属性添加到任何策略断言中,以使该断言成为选项而不是要求,即使断言是<wsp:All>
或<wsp:Policy>
元素。
策略替代方案似乎是一个潜在有用的功能,但是很难提出一个平凡的工作示例。 在实践中使用此功能的情况通常是使安全处理的特定组件(例如UsernameToken
)可选。 更复杂的替代方案(例如,允许客户端以UsernameToken
或X.509证书的形式提供标识)似乎超出了当前WS-SecurityPolicy实现的能力。
在WSDL 1.1(有些过时,但仍是服务定义中使用最广泛的形式)中,服务定义使用分层结构。 第一(底部)层由<wsdl:message>
元素组成,这些元素定义了往返于服务的消息的XML结构。 第二层是<wsdl:portType>
元素,它们定义操作集,每个操作由输入,输出或故障消息指定。 第三层是<wsdl:binding>
元素,它们将特定的消息协议(例如SOAP)和访问方法与<wsdl:portType>
关联。 第四层是<wsdl:port>
元素形式的服务端点定义,该元素指定可以访问<wsdl:binding>
的地址。
WS-Policy允许您在与这些定义层不完全匹配的几个不同点将策略附加到WSDL服务定义。 尽管这些层代表了服务定义的逻辑结构,但是WS-Policy更关注消息和消息分组。 WS-Policy使用的消息分组的四个级别是:
<wsdl:message>
元素附加了策略,或者通过特定操作的输入/输出/故障定义附加到特定操作中,则该消息将在任何地方使用。 <wsdl:portType>
或<wsdl:binding>
元素)。 <wsdl:binding>
或<wsdl:portType>
内的<wsdl:operation>
元素附加的策略)。 <wsdl:port>
或<wsdl:binding>
附加的策略)或基于特定端口类型的所有服务绑定的所有消息交换(附加到该<wsdl:portType>
)。 <wsdl:service>
元素上)。 用于WSDL的主要策略附加机制与用于在另一个策略中引用一个策略的机制相同-在“ 策略包含”部分中讨论了<wsp:PolicyReference>
元素。 可以将此WS-Policy元素添加为任何先前列出的WSDL元素的子元素,以指定要在该消息分组级别上应用的策略。 您还可以将策略直接作为带有任何适当内容的<wsp:Policy>
元素嵌入,但是通常最好使用引用,以便WSDL结构保持整洁。
在较低级别上,在较低级别的消息组中继承了在消息分组的一级应用的策略,这些策略在<wsp:All>
元素内进行组合。 这使得应用于每个消息的实际(或以WS-Policy术语表示, 有效 )策略是应用于消息,操作,端点和服务层的所有策略的结合。 因此,策略不仅取决于消息本身,还取决于使用消息的上下文。
清单4演示了它是如何工作的,显示了带有策略引用的基本WSDL定义:
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="#UsernameToken"/>
<wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="addBook">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy" URI="#AsymmEncr"/>
...
</wsdl:operation>
</wsdl:binding>
在这种情况下,在<wsdl:binding>
级别上附加了需要UsernameToken
的策略,并且在该绑定的一部分定义的addBook
操作上附加了需要非对称消息加密的其他策略。 假设此示例显示了WSDL的完整策略引用集,则始终需要UsernameToken
,但是消息签名仅用于addBook
操作。
作为使用<wsp:PolicyReference>
直接从WSDL元素引用策略的替代方法,可以使用wsp:PolicyURIs
属性。 您可以将此属性添加到可以附加策略的任何WSDL元素。 它的功能基本上与使用<wsp:PolicyReference>
子元素相同。
WS-SecurityPolicy指定消息分组级别,在该级别可以将不同类型的策略断言附加到服务描述。 例如,用于指定传输安全性的<sp:TransportBinding>
断言只能附加在端点级别,而用于指定消息加密或签名的<sp:AsymmetricBinding>
和<sp:SymmetricBinding>
断言只能在以下位置使用:端点或操作级别。
尽管<sp:AsymmetricBinding>
或<sp:SymmetricBinding>
不能在消息级别指定, 可以指定消息成分进行加密或在消息级别签署。 这意味着从理论上讲至少可以在每个消息的基础上指定加密或签名。
既然您已经了解了WS-Policy的原理以及它如何与WSDL结合使用,现在该尝试使用这些原理的一些策略示例了。 与以前的文章一样,我使用了所有三个主要的Java开放源Web服务堆栈(Axis2,Metro和CXF)尝试了此代码。
清单5显示了一个在WSDL服务定义中使用三个级别的策略附件的示例(示例代码下载中的effective1.wsdl)。 使用的三个策略是:
UsernameToken
:需要带哈希密码的UsernameToken
。 SymmEncr
:要求使用客户端生成的密钥进行对称加密。 EncrBody
:需要对邮件正文进行加密。 <wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"...>
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
<sp:SupportingTokens>
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:HashPassword/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:Policy>
<wsp:Policy wsu:Id="SymmEncr" xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=".../IncludeToken/Never">
...
</sp:X509Token>
</wsp:Policy>
</sp:ProtectionToken>
...
</wsp:Policy>
</sp:SymmetricBinding>
...
</wsp:Policy>
<wsp:Policy wsu:Id="EncrBody" xmlns:wsp="http://www.w3.org/ns/ws-policy"...>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
</wsp:Policy>
...
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#UsernameToken"/>
...
<wsdl:operation name="getBook">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SymmEncr"/>
<wsdlsoap:operation soapAction="urn:getBook"/>
<wsdl:input name="getBookRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBookResponse">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#EncrBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getBooksByType">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SymmEncr"/>
<wsdlsoap:operation soapAction="urn:getBooksByType"/>
<wsdl:input name="getBooksByTypeRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBooksByTypeResponse">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#EncrBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getTypes">
...
</wsdl:operation>
<wsdl:operation name="addBook">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SymmEncr"/>
<wsdlsoap:operation soapAction="urn:addBook"/>
<wsdl:input name="addBookRequest">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#EncrBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="addBookResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="addDuplicateFault">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#EncrBody"/>
<wsdlsoap:fault name="addDuplicateFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
...
</wsdl:definitions>
清单5 WSDL文档中的策略引用(以粗体显示)将UsernameToken
策略附加到<wsdl:binding>
,因此所有操作都需要UsernameToken
。 对于交换书籍信息的所有操作, SymmEncr
策略附加到单独的<wsdl:operation>
,而EncrBody
策略附加到包含书籍信息的消息上,因此书籍信息总是以加密形式发送。
这是一个棘手的策略,因为它要求客户端生成一个密钥并将其与请求消息一起发送到服务器,即使该密钥仅用于加密响应也是如此。 Axis2 1.5.1(尝试了1.5.2发行版,但缺少安全处理所需的文件)在生成的代码和服务器操作中完全忽略了该策略,愉快地运行而没有任何安全性。 当我更改策略以使用较旧的提交名称空间时,除处理addBook
操作故障响应外,Axis2会识别该策略并正确运行。 根据该策略,返回的应用程序故障响应应该使用加密,但是Axis2未加密地将其发送回去。
Metro生成了带有UsernameToken
的请求消息,但没有密钥信息,这在第一次消息交换中完全失败。 CXF 2.3.0的性能比Metro好得多,除了两种情况外,CXF 2.3.0可以正确处理策略。 当addBook
操作成功时,响应消息不使用加密。 CXF服务器正确处理了此问题,但是客户端在处理响应时引发了异常。 另一个CXF错误与Axis2相同,未对应用程序故障响应使用加密。
清单5策略演示了消息加密的选择性使用,仅加密那些包含书籍信息的消息。 但是,此策略使用对称加密。 能够使用非对称加密(客户端具有自己的证书)(特别是当您希望对邮件进行签名以进行发件人验证时)进行相同类型的事情,这将是很棒的。 清单6显示了为此目的设计的示例(在download中提供了valid2.wsdl )。 这个仅使用WSDL中的两个策略:
AsymmBinding
:需要使用双重证书的非对称加密。 SignBody
:需要对邮件正文进行签名。 <wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"...>
<wsp:Policy wsu:Id="AsymmBinding" xmlns:wsp="http://www.w3.org/ns/ws-policy" ...>
<sp:AsymmetricBinding>
<wsp:Policy>
<sp:InitiatorToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=".../IncludeToken/AlwaysToRecipient">
...
</sp:X509Token>
</wsp:Policy>
</sp:InitiatorToken>
<sp:RecipientToken>
<wsp:Policy>
<sp:X509Token sp:IncludeToken=".../IncludeToken/Never">
...
</sp:X509Token>
</wsp:Policy>
</sp:RecipientToken>
...
</wsp:Policy>
</sp:AsymmetricBinding>
</wsp:Policy>
<wsp:Policy wsu:Id="SignBody" xmlns:wsp="http://www.w3.org/ns/ws-policy" ...>
<sp:SignedParts>
<sp:Body/>
</sp:SignedParts>
</wsp:Policy>
...
<wsdl:binding name="LibrarySoapBinding" type="wns:Library">
...
<wsdl:operation name="getBook">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#AsymmBinding"/>
<wsdlsoap:operation soapAction="urn:getBook"/>
<wsdl:input name="getBookRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBookResponse">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SignBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getBooksByType">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#AsymmBinding"/>
<wsdlsoap:operation soapAction="urn:getBooksByType"/>
<wsdl:input name="getBooksByTypeRequest">
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="getBooksByTypeResponse">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SignBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="getTypes">
...
</wsdl:operation>
<wsdl:operation name="addBook">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#AsymmBinding"/>
<wsdlsoap:operation soapAction="urn:addBook"/>
<wsdl:input name="addBookRequest">
<wsp:PolicyReference xmlns:wsp="http://www.w3.org/ns/ws-policy"
URI="#SignBody"/>
<wsdlsoap:body use="literal"/>
</wsdl:input>
<wsdl:output name="addBookResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
<wsdl:fault name="addDuplicateFault">
<wsdlsoap:fault name="addDuplicateFault" use="literal"/>
</wsdl:fault>
</wsdl:operation>
</wsdl:binding>
...
</wsdl:definitions>
清单6的示例使用非对称加密对所有提供书籍信息的消息进行签名。 这意味着getBook
和getBooksByType
响应消息应由服务器签名,而addBook
请求消息应由客户端签名。 因为这是使用非对称加密的,其中每一方都有自己的证书和私钥,所以它应该比清单5的对称加密示例更易于处理。
Axis2以与先前示例相同的方式失败,使用WS-Policy 1.5策略名称空间完全忽略了策略组件。 当我更改为提交名称空间时,Axis2能够处理此示例而没有任何错误。 由于在将WS-Policy 1.5名称空间与Axis2一起使用时存在这些问题,因此代码下载中的Axis2示例全部使用了提交名称空间。
Metro无法使用提供的此策略配置,仅在第一次请求时在客户端上抛出NullPointerException
。 经过一番调查,我发现,如果我在端点级别而不是仅在操作和消息级别附加策略,则问题就消失了。 Metro示例包含#AsymmBinding
<wsdl:binding>
引用的具有#AsymmBinding
策略的#AsymmBinding
,并且该示例运行没有问题(尽管像对称情况下的CXF一样,Metro不会对应用程序故障应用安全性响应)。
CXF也因清单6策略配置而失败,但是在当前代码中没有任何简单的解决方法。 CXF客户端代码在发送getBook
请求消息时错误地生成了签名,然后服务器代码无法处理请求消息。 所以它看起来像当前CXF代码的生成签名坚持当AsymmetricBinding
是在范围上,甚至当签署什么。
WS-Policy定义了一种灵活而强大的结构来表达任何形式的约束。 不幸的是,Web服务堆栈使用的WS-Policy和WS-SecurityPolicy处理的实现并没有实现很大的灵活性。 由于缺乏实现支持,因此WS-Policy的许多其他有用功能无法用于旨在与所有Web服务堆栈进行互操作的Web服务。
基本有效策略处理(将策略附加到WSDL服务定义中的不同点)是策略和WSDL设计的核心功能,应在适合您的服务的地方使用。 但是,这种类型的配置的潜在有用功能之一-分别选择性地签名和加密消息的能力-不能可靠地工作(只有Apache Axis2可以正确处理测试用例,然后才能更改策略名称空间) 。 鉴于此限制,如果您想要最佳的互操作性,最好<wsdl:binding>
保持<wsdl:binding>
和<wsdl:operation>
级别的策略附件。
外部策略对于SOA类型的环境尤其有用,在SOA类型的环境中,可以设置一组通用策略以供整个组织使用,并且每个服务都可以引用适合其需求的策略。 即使目前所有开源Java Web服务堆栈都不支持此功能(只有Apache CXF正确处理了该功能),大型组织还是希望使用该功能并将Web服务实现限制为使用其中一个堆栈(无论是开源的还是商业的)支持它。 您还可以通过其他方式(例如使用WSDL包含)获得相同的效果。
在本系列的下一篇文章中,我将总结三个主要Java Web服务堆栈的性能和互操作性问题,并概述如何比较这些堆栈以实现安全的Web服务。 如果您在组织中使用安全的Web服务,那么您将不会错过这一点。
翻译自: https://www.ibm.com/developerworks/java/library/j-jws18/index.html