使用 UsernameToken 来认证 Web Service 客户机
WebSphere® Application Server Liberty 支持 OASIS Web Service 安全性用户名令牌概要文件 1.1 规范。此规范描述 Web Service 客户机如何提供 UsernameToken,作为确定请求者的手段,方式是使用用户名以及选择对 Web Service 提供者使用密码或密码等价项。Liberty 中用于为 Web Service 提供者处理此策略的 Web Service 安全性 (WS-Security) 运行时可以使用此标识信息来认证用户。
UsernameToken 的需求表示为 WS-Security 策略中的其中一个支持令牌。可以添加 UsernameToken 需求,作为其中一个支持令牌断言中的必需令牌,包括 SupportingTokens、SignedSupportingTokens、SignedEndorsingSupportingTokens、SignedEncryptedSupportingTokens 和 EncryptedSupportingTokens。
<sp:SupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
除了必须提供用户名或密码之外,您还可以配置策略以在 UsernameToken 中包含 nonce 和 created 时间戳记。
<sp:SupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
<sp13:Created />
<sp13:Nonce />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<sp:SupportingTokens>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken11 />
<sp:HashPassword />
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
有关 nonce、created 以及不同密码类型的更多信息,请参阅 OASIS WS-Security 策略 1.3 规范。
在 Web Service 客户机中提供用户名和密码
在生成 UsernameToken 时,Liberty 中的 WS-Security 功能部件提供了多种方法来指示客户机应用程序的用户名和密码。可以通过程序来设置用户名和密码,也可以在 server.xml 文件中设置。
客户机可以使用 server.xml 文件中提供的用户名和密码来生成 UsernameToken。server.xml 文件中的用户名和密码被认为是缺省配置,会被 RequestContext 上为客户机的 Web Service 调用所提供的用户名和密码覆盖。
<wsSecurityClient id="default"
ws-security.username="alice"
ws-security.callback-handler="com.acme.PasswordCallback"
</wsSecurityClient>
- ws-security.username - 用户名
- ws-security.password - 用户密码(如果未定义 ws-security.callback-handler)
- ws-security.callback-handler - 用来获取密码的 CallbackHandler 实现类
Map<String, Object> requestCtx = ((BindingProvider)port).getRequestContext();
requestCtx.put("ws-security.username", "bob_username");
requestCtx.put("ws-security.password", "bob_password");
在 Web Service 提供者中使用 UsernameToken
收到 UsernameToken 后,WS-Security 会自动使用 Liberty 安全用户注册表来验证用户名和密码(如果需要密码)。如果 UsernameToken 中的密码类型是 PasswordDigest 或者使用的是派生密钥,那么您必须通过在 server.xml 文件中配置密码回调处理程序的 ws-security.callback-handler 实现来提供该实现。此回调处理程序必须返回所期望的所有用户名的有效密码,以便 WS-Security 运行时可以计算摘要值,以与 SOAP 消息中的值进行比较。成功完成对摘要值进行比较之后,将针对用户注册表来验证用户名和密码。
<wsSecurityProvider id="default"
ws-security.callback-handler="com.acme.PasswordCallback"
</wsSecurityProvider>
密码 CallbackHandler
WS-Security 使用密码 CallbackHandler 来检索用户密码。在 Liberty 中,此密码 CallbackHandler 类必须打包成 Liberty 功能部件。有关密码 CallbackHandler 的更多信息,请参阅为 WS-Security 开发密码回调处理程序。
有关回调处理程序实现的要求和局限性的更多信息,请参阅使用 X.509 令牌保护 Web Service 的“专用密钥密码 CallbackHandler”一节。
在 SOAP 消息中保护 UsernameToken
<UsernameToken>
<Username>myusername</Username>
<Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">
mypassword
</Password>
</UsernameToken>
当您想要随 PasswordText 发送 UsernameToken 时,请考虑对消息进行更多保护,例如,使用 HTTPS,或者通过使用 EncryptedSupportingToken 策略断言对令牌进行加密。有关要求在策略中使用 HTTPS 传输的更多信息,请参阅 Liberty:Web Service 安全性 HTTPS 传输策略断言。
UsernameToken 密钥派生
如 Web Service 安全性用户名令牌概要文件 1.1 规范中所述:
可以使用与用户名相关联的密码来派生共享密钥,以实现完整性或机密性,从而保护消息内容。
必须注意,密码会经受多种类型的攻击,这又会导致泄露所派生的任何密钥。此密钥派生过程旨在尽可能降低对密钥进行攻击的风险,但最终还是会受到为了便于人们记住密码和在标准键盘上输入密码而对密码造成的不安全性的限制。
为了能够从密码派生密钥,还需要另外两个元素。这两个元素是 <wsse11:Salt> 和 <wsse11:Iteration>。这些值不是秘密,当使用了密钥派生时,必须在 Username 令牌中传递这些值。当使用了密钥派生时,密码不得包括在 Username 令牌中。接收方将利用它对密码的了解来派生与发送方相同的密钥。
如果 UsernameToken 正在对提供者应用程序使用密钥派生,那么您必须通过在 server.xml 文件中配置密码回调处理程序的 ws-security.callback-handler 实现来提供该实现。
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:WssUsernameToken10 />
<sp:RequireDerivedKeys />
</wsp:Policy>
</sp:UsernameToken>
<wsp:Policy>
</sp:ProtectionToken>
</wsp:Policy>
</sp:SymmetricBinding>
<wsse:UsernameToken wsse:Id="...">
<wsse:Username>...</wsse:Username>
<wsse11:Salt>...</wsse11:Salt>
<wsse11:Iteration>...</wsse11:Iteration>
</wsse:UsernameToken>