首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

Metro 服务上的 WS-Security

2012-09-06 
Metro 服务下的 WS-Security本文展示如何通过 Metro 来使用和配置 WS-Security,将其作为一个独立的 Web 应

Metro 服务下的 WS-Security

本文展示如何通过 Metro 来使用和配置 WS-Security,将其作为一个独立的 Web 应用程序在 Glassfish 服务器外部使用。参见 下载 部分获取本文中的全部示例的完整源代码,该代码实现了此前在本系列中使用的简单图书馆管理服务。

<wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#UsernameToken"/> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getBook"> <wsdlsoap:operation soapAction="urn:getBook"/> <wsdl:input name="getBookRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="getBookResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> ... </wsdl:binding> <wsdl:service name="MetroLibrary"> <wsdl:port binding="wns:LibrarySoapBinding" name="library"> <wsdlsoap:address location="http://localhost:8080/metro-library-username"/> </wsdl:port> </wsdl:service> <!-- Policy for Username Token with plaintext password, sent from client to server only --> <wsp:Policy wsu:Id="UsernameToken" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <sp:SupportingTokens xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <wsp:Policy> <sp:UsernameToken sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/> </wsp:Policy> </sp:SupportingTokens> </wsp:All> </wsp:ExactlyOne> </wsp:Policy></wsdl:definitions>

?

清单 1 WSDL 告诉我们,要访问服务需要进行哪些安全处理。您需要同时在服务器端和客户端向策略信息中添加 WSDL 自定义扩展,通过用户配置细节表明如何实现安全处理。这些自定义扩展被加入到了 WSDL 中的 <wsp:Policy> 组件。下一步,我将向您展示每一端的扩展示例。

<wssc:CallbackHandlerConfiguration wspp:visibility="private" xmlns:wssc="http://schemas.sun.com/2006/03/wss/client" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"> <wssc:CallbackHandler name="usernameHandler" classname="com.sosnoski.ws.library.metro.UserPassCallbackHandler"/> <wssc:CallbackHandler name="passwordHandler" classname="com.sosnoski.ws.library.metro.UserPassCallbackHandler"/> </wssc:CallbackHandlerConfiguration> </wsp:All> </wsp:ExactlyOne></wsp:Policy>

?

在 清单 2 中,所有的回调必须使用相同的类。清单 3 是回调类的代码,作用是检查每个回调请求的类型并恰当地为其赋值:


清单3. 客户端回调代码

<wsss:ValidatorConfiguration wspp:visibility="private" xmlns:wsss="http://schemas.sun.com/2006/03/wss/server" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"> <wsss:Validator name="usernameValidator" classname="com.sosnoski.ws.library.metro.PasswordValidator"/> </wsss:ValidatorConfiguration> </wsp:All> </wsp:ExactlyOne></wsp:Policy>

?

清单 4 中的服务器端 WSIT 扩展以 <wsss:ValidatorConfiguration> 元素和 <wsss:Validator> 子元素形式表示,指定将作为验证器回调使用的类。清单 5 给出了这个类的代码,这个类必须实现 com.sun.xml.wss.impl.callback.PasswordValidationCallback.PasswordValidator 接口。在这里,它只是针对固定值检查提供的用户名和密码,但它可以轻松使用一个数据库查询或其他机制替代。


清单5. 服务器回调代码

<wsp:PolicyReference xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" URI="#SignEncr"/> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getBook"> <wsdlsoap:operation soapAction="urn:getBook"/> <wsdl:input name="getBookRequest"> <wsdlsoap:body use="literal"/> </wsdl:input> <wsdl:output name="getBookResponse"> <wsdlsoap:body use="literal"/> </wsdl:output> </wsdl:operation> ... </wsdl:binding> <wsdl:service name="MetroLibrary"> <wsdl:port binding="wns:LibrarySoapBinding" name="library"> <wsdlsoap:address location="http://localhost:8080/metro-library-username"/> </wsdl:port> </wsdl:service> <!-- Policy for first signing and then encrypting all messages, with the certificate included in the message from client to server but only a thumbprint on messages from the server to the client. --> <wsp:Policy wsu:Id="SignEncr" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <wsp:ExactlyOne> <wsp:All> <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"> <!-- Added this policy component so Metro would work with the same certificates (and key stores) used in the Axis2/Rampart example. --> <wsp:Policy> <sp:RequireThumbprintReference/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:InitiatorToken> <sp:RecipientToken> <wsp:Policy> <sp:X509Token sp:IncludeToken=".../IncludeToken/Never"> <wsp:Policy> <sp:RequireThumbprintReference/> </wsp:Policy> </sp:X509Token> </wsp:Policy> </sp:RecipientToken> <sp:AlgorithmSuite> <wsp:Policy> <sp:TripleDesRsa15/> </wsp:Policy> </sp:AlgorithmSuite> <sp:Layout> <wsp:Policy> <sp:Strict/> </wsp:Policy> </sp:Layout> <sp:IncludeTimestamp/> <sp:OnlySignEntireHeadersAndBody/> </wsp:Policy> </sp:AsymmetricBinding> <sp:SignedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <sp:Body/> </sp:SignedParts> <sp:EncryptedParts xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702"> <sp:Body/> </sp:EncryptedParts> </wsp:All> </wsp:ExactlyOne> </wsp:Policy></wsdl:definitions>

?

清单 6 WSDL 与先前的 Axis2/Rampart 示例中使用过的 WSDL 的唯一重要区别是:当 X509 证书没有被包含到一条信息中时,需要向 <sp:InitiatorToken> 组件添加一个要求使用拇指指纹引用的策略,其原因是 Metro 和 Axis2 中引用的默认处理方式不同。

当客户端(在 WS-SecurityPolicy 术语中称为发起者)发送一条信息时,客户端的 X.509 证书也作为信息的一部分发送(因为<sp:InitiatorToken/wsp:Policy/sp:X509Token> 元素上的 sp:IncludeToken=".../IncludeToken/AlwaysToRecipient" 属性),然后服务器使用该证书进行签名验证。当服务器对客户端进行应答时,进行加密处理时需要引用那个证书。如果没有指定其他方法,Axis2/Rampart 默认使用一个拇指指纹引用进行证书识别。Metro/WSIT 默认使用另一种方法,称为主体密匙标识符(subject key identifier,SKI)。Axis2/Rampart 示例中使用的证书的形式并不支持 SKI,所以它们默认不能用于 Metro/WSIT。向策略中添加 <sp:RequireThumbprintReference/> 元素告知 Metro/WSIT 使用拇指指纹引用来代替证书。

这种策略改变使先前的 Axis2/Rampart 示例使用的证书和密匙存储可以在现在的示例中使用。这还使 Axis2/Rampart 客户端示例可以与 Metro/WSIT 服务器一起使用,反之也然,从而作为一种检查互操作性的便捷方式。如果您进行这种尝试(方法是修改每次传送到测试客户端的目标路径),就会发现大部分消息可以毫不费力地交换 — 但是在实际操作中有一个问题,这将在下面的 互操作性问题 小节进行讨论。

UsernameToken 示例一样,WSIT 需要客户端与服务器上存在针对策略信息的自定义扩展,以便提供详细的附加配置信息。

<wssc:KeyStore alias="clientkey" keypass="clientpass" location="client.keystore" storepass="nosecret" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private" xmlns:wssc="http://schemas.sun.com/2006/03/wss/client"/> <wssc:TrustStore location="client.keystore" peeralias="serverkey" storepass="nosecret" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private" xmlns:wssc="http://schemas.sun.com/2006/03/wss/client"/> </wsp:All> </wsp:ExactlyOne></wsp:Policy>

?

清单 7 WSIT 自定义扩展提供了访问密匙存储和可信存储(在本例中是同一个文件)所需的全部参数,包括访问客户端的私有密匙所需的密码(<wssc:KeyStore> 元素上的 keypass="clientpass" 属性)。也可以使用回调获取密码信息,这将在下节介绍。

已命名的密匙存储和可信存储必须放在类路径目录下的 META-INF 子目录中。也可以对这些文件使用绝对路径 — 而不是仅仅使用文件名 — 这允许您在文件系统的任意固定地址定位它们。(回想一下,对于客户端,包含 WSIT 自定义扩展的 WSDL 必须使用固定名称 wsit-client.xml,而且必须在类路径的根目录下或者类路径根目录下的 META-INF子目录中)。

<wsss:KeyStore alias="serverkey" keypass="com.sosnoski.ws.library.metro.KeystoreAccess" location="server.keystore" storepass="nosecret" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private" xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"/> <wsss:TrustStore location="server.keystore" storepass="nosecret" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" wspp:visibility="private" xmlns:wsss="http://schemas.sun.com/2006/03/wss/server"/> </wsp:All> </wsp:ExactlyOne></wsp:Policy>

?

清单 9 展示了这个示例使用的 CallbackHandler 接口的实现:


清单 9. 服务器密匙存储密码回调代码

描述名字大小下载方法本文源代码j-jws10.zip38KBHTTP


原文:http://www.ibm.com/developerworks/cn/java/j-jws10.html

热点排行