通过 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。在右窗格中,单击 myrealmmyrealm 表示当前 WebLogic Server 的安全配置。我们将向该配置添加一个测试用户。单击 Users and Groups 选项卡。单击 New 按钮。

Name 域中,输入 suzie。在 Description 中,输入 An authenticated Web service user。在 PasswordConfirm 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.javamain 方法添加下面 突出显示的代码:

  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 的安全性配置概述

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 的结合为这个问题提供了一个极好的解决方案,使开发人员得以轻松地部署和维护企业服务。

参考资料

  • Eclipse Documentation — 关于如何使用 Eclipse 的文档
  • Ant — Ant 工具的官方 Web 站点
  • OASIS Web Services Security — 官方 Web 服务安全规范之家
  • Gary Ng 是 WebAge Solutions 的高级顾问,自 2001 年以来参与过各种 J2EE 项目。

    Matt Silver 是技术顾问兼培训师,目前是 WebAge Solutions 的高级顾问。