主题
企业架构
通过 WebLogic Server 9.2 保护 Web 服务
页面: 1, 2, 3
现在我们将了解如何为服务添加机密性。这意味着希望在客户端和服务器之间加密消息(SOAP 体)。其基本过程与添加消息的完整性一样:批注并重新生成服务,然后更新客户端。
在 WTP 中打开 HelloWorldService.java。添加以下 突出显示的批注:
@Policies({
@Policy(uri="policy:Sign.xml")
,
@Policy(uri="policy:Encrypt.xml")
})
(别忘了在 Sign.xml 批注后面后添加逗号。)
这个批注指定我们希望客户端和服务器使用加密。默认加密是双向的(即,从客户端到服务器和从服务器到客户端两个方向)。如果只要求单向加密,可向批注添加可选的 direction 属性来处理这一问题。
现在需要重新构建服务。在命令 shell 窗口中,运行 ant 命令。如前,您将看到 BUILD SUCCESSFUL 消息。
现在,更新客户端。首先,像以前那样从浏览器获得 WSDL 文件并保存。用编辑器打开它。您将注意到一个新的元素: wssp:Confidentiality。这示意客户端应使用加密。另请注意如下所示的 Encypt.xml 策略的内容:
<wsp:Policy s0:Id="Encrypt.xml"> ... </wsp:Policy> ... <portType name="HelloWorldPortType" wsp:PolicyURIs="#Sign.xml #Encrypt.xml"> .. </portType>
由于新的部署重新生成了 WSDL 文件,我们需要再为监视器更新端口号。WSDL 文件末尾处有如下代码:
<s2:address location="http://localhost:7001/HelloWorldService/HelloWorldService"<//>
将端口号更改为 7002,如下所示:
<s2:address location="http://localhost: 7002/HelloWorldService/HelloWorldService"/>
保存并关闭 WSDL 文件。在命令 shell 中,运行 ant -buildfile gen-client.xml 命令。您应该会看到一条 BUILD SUCCESSFUL 消息。客户端代理已经更新了。
下面还要做什么呢?实际上不需要任何改动了。客户端无需添加任何代码来加密消息。客户端代理将提供所有的加密工作。这是使用 Web 服务安全机制的一个主要优点;开发人员无需编写任何加密代码!
运行 HelloWorldClient。您将看到正常的问候响应。有什么改变了?初看起来似乎并无变化。然而,检查 TCP/IP 监视器,您将看到请求和响应已经加密了;无法像先前那样找到 <name> 元素。这里有 <CipherData> 元素和一些加密的文本。注意,只是加密了消息体(请求的 name 元素和响应的 return 元素);所有消息头都没有加密。另请注意,安全头 ( wsse:Security) 已经添加了 ns1:EncryptedKey 元素。
消息机密性已经被加入服务了!
接下来,我们可以向 Web 服务添加授权机制。简单地说,我们可以强制客户端随 SOAP 请求提供用户名和口令;如果 WebLogic Server 的用户注册表不包含该用户名和口令,则服务器将拒绝对服务的访问。这允许一种形式的访问控制。注意,这与消息的完整性中的身份识别不同。消息完整性通过证书进行客户端识别;权限涉及客户端是否实际有权调用服务。如果客户端未能成功地通过 WebLogic Server 的用户注册表身份验证却试图调用服务,则服务器将拒绝对服务的访问。
在本教程的这一部分,我们要向 WebLogic Server 的用户注册表添加一个用户,然后修改服务强制客户端进行身份验证。然后我们将使用客户端进行测试。
第一步是在 WebLogic Server 的用户注册表中创建一个用户。默认情况下,用户注册表是 WebLogic Server 附带的一个嵌入式 LDAP 服务器,可以通过 WebLogic Server 管理控制台向其中添加用户。确保服务器在运行,然后使用浏览器浏览到 http://localhost:7001/console。使用用户名 weblogic 和口令 password 登录。管理控制台将打开。
在左侧的 Domain Structure 窗格中,单击 Security Realms。在右窗格中,单击 myrealm。 myrealm 表示当前 WebLogic Server 的安全配置。我们将向该配置添加一个测试用户。单击 Users and Groups 选项卡。单击 New 按钮。
在 Name 域中,输入 suzie。在 Description 中,输入 An authenticated Web service user。在 Password 和 Confirm Password 域中,输入 munchkin。单击 OK。
我们已经在 WebLogic Server 的用户注册表中创建了一个新用户。现在可以编辑服务,要求所有客户端给出用户名/口令(希望与注册表中的用户匹配)进行身份验证。在 WTP 中,打开 HelloWorldService.java 并添加以下 突出显示的批注。
@Policies({
@Policy(uri="policy:Sign.xml"),
@Policy(uri="policy:Encrypt.xml")
,
@Policy(uri="policy:Auth.xml"
,direction=Policy.Direction.inbound)
})
新的批注指定强制实施授权策略,但只针对入站流量。(在本例中,强制服务器对客户端进行反向身份验证意义不大。)
保存此文件。应该不会出现错误。现在可以构建并部署服务了在命令 shell 窗口中运行 ant 命令。如前,您将看到 BUILD SUCCESSFUL 消息。
既然已经重新生成服务,则必须像前面所做的那样重新生成客户端代理。像以前那样从浏览器获得 WSDL 文件并保存。用编辑器打开它。将出现一个新的元素 wssp:Identity。它示意客户端在调用服务时应该发送用户名和口令。另请注意如下所示的新 Auth.xml 策略的内容:
<wsp:Policy s0:Id="Auth.xml"> ... </wsp:Policy> ... <input> <s2:body parts="parameters" use="literal"/> <wsp:Policy> <wsp:PolicyReference URI="#Auth.xml"/> </wsp:Policy> </input>
与前面一样,由于新的部署重新生成了 WSDL 文件,我们需要为监视器更新端口号。WSDL 文件末尾处有如下代码:
<s2:address location="http://localhost:7001/HelloWorldService/HelloWorldService"/>
将端口号更改为 7002,如下所示:
<s2:address location="http://localhost: 7002/HelloWorldService/HelloWorldService"/>
保存并关闭 WSDL 文件。现在,在命令 shell 中,运行 ant -buildfile gen-client.xml 命令。您应该会看到一条 BUILD SUCCESSFUL 消息。客户端代理已经更新了。
返回 WTP,刷新 WSTest 项目。运行 HelloWorldClient 类。发生了什么?
javax.xml.rpc.soap.SOAPFaultException:Unable to add security token for identity
客户端试图调用服务,但又不提供任何授权 凭证。我们需要更改客户端代码,以便使用刚才创建的用户名/口令 suzie/munchkin 来调用服务。现在开始向 HelloWorldClient.java 的 main 方法添加下面 突出显示的代码:
stub._setProperty( WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
String username = "suzie";
String password = "munchkin";
cp = new ClientUNTCredentialProvider(username.getBytes(),
password.getBytes());
credProviders.add(cp);
stub._setProperty(
运行代码。现在应当返回正常的问候消息。我们现在知道客户端调用服务前被强制添加凭证。查看监视器,检查请求。应该看到一个新部分:
<wsse:UsernameToken> <wsse:Username>suzie</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/ oasis-200401-wss-username-token-profile-1.0#PasswordText">munchkin</wsse:Password> </wsse:UsernameToken>
这些的确是我们提供的凭证。注意,这些凭证以纯文本传输。WS-Security 规范没有涉及用户凭证加密;而是推荐采用传输层安全性(即,保护整个 TCP/IP 套接字)。
我们已经成功地将身份验证加入 Web 服务了!
WebLogic Server 10 最近已发布。对于现有的受保护的 Web 服务,这意味着什么呢?幸运的是,变化不是很多。版本 10 中服务的部署和运行没有变化。然而,客户端代码需要使用版本 10 的客户 API 重新生成。此外,WebLogic Server 10 增加了 WS-SecurityPolicy 1.2 支持,现在它支持 WS-Security 1.1。(WebLogic Server 9.2支持 WS-Security 1.0。)
WS-SecurityPolicy 1.2 的重要性在于可以创建与 BEA 专有安全策略文件相对的“标准”安全策略文件。WS-SecurityPolicy 规范发布之前发布的 WebLogic Server 9.2 使用的是依据采用专有 BEA 安全策略模式的旧版 WS-Policy 规范编写的安全策略文件。
应该采用哪一种策略文件?BEA 建议采用 S-SecurityPolicy 标准策略文件代替其专有策略文件。实际上,版本 10 同时支持这两种策略文件,但这二者是不兼容的,所以一个给定的 Web 服务只能采用二者之一。
然而,在您急着将 WebLogic Server 9.2 策略文件移植到新标准之前,谨记 WS-SecurityPolicy 尚有局限之处,因为在 BEA 实现它的时候,它还只是(依然是)一个草案。具体来说,如果您需要元素级的数字签名和/或加密(即,您不必对整个消息体进行数字签名和/或加密),或者要求 SAML 1.1,那么您仍然必须采用专有的 BEA WebLogic 9.2 型策略。
根据 WS-Security,尽管 WebLogic Server 10 支持 WS-Security 1.1,但为了便于互操作性,BEA 仍然推荐使用 WS-Security 1.0 策略。只是当您要求更强的安全性时,才应该采用 WS-Security 1.1 策略。而且,只有使用新的 WS-SecurityPolicy 1.2 策略文件,才支持 WS-Security 1.1。
在本文中,我们讨论了 Web 服务安全性的三个方面:消息完整性、消息机密性和身份验证。我们已经看到编写包含这三个方面的“安全”Web 服务非常简单;所要做的只是用适当的批注来批注 Web 服务代码。我们了解了使用什么批注来实现每个方面,弄清了必须如何更改客户端代码调用受保护的服务,看到了 SOAP 消息自身如何改变以反映新加入的安全性。在本教程中,我们构建了一个 Web 服务并逐步加入所有三个方面。
由于 SOAP 消息的“纯文本”的性质,当我们部署 Web 服务作为企业生产环境的一部分的时候,强大的安全性是非常重要的。WS-Security 与 WebLogic Server 的结合为这个问题提供了一个极好的解决方案,使开发人员得以轻松地部署和维护企业服务。
Gary Ng 是 WebAge Solutions 的高级顾问,自 2001 年以来参与过各种 J2EE 项目。
Matt Silver 是技术顾问兼培训师,目前是 WebAge Solutions 的高级顾问。