使用策略集构建符合WS-security安全规范的JAX-WS Web Service客户端

JAX-WS 的 Web Service 可以通过满足 WS-Security 规范来提供安全的 Web Service,但是也需要满足 WS-Security 的 Web Service 客户端才能调用。本文结合 WebSphere 里的开发工具 AST(Application Server Toolkit) 介绍了使用 WebSphere 策略集开发满足 WS-Security 的 standalone 的 Web Service 客户端,使其在不依赖于 WAS 的 J2EE 容器环境下也能调用安全的 Web Service。

引言

WebSphere Application Server 6.1(WAS6.1)的 Web Service Feature Pack 提供了对 JAX-WS 2.0 这种新的 Web Service 标准的支持。同时,通过策略集(Policy Set)的方式,来满足 Web Service 的服务质量(QoS)。其中,WS-Security 规范使用了消息加密和数字签名的方法来保证 SOAP 消息在传送中的安全性和完整性。Web Service 客户端在调用使用了 WS-Security 的 Web Service 的时候,自身也必须满足 WS-Security 的规范。如果客户端是使用 WebSphere Application Server 6.1(加上 Web Service Feature Pack)作为容器的 J2EE 应用,我们可以通过和服务器端同样的方式来配置 WS-Security 所要使用的证书和密钥。但是并不是所有的 Web Service 客户端都是 J2EE 项目,并且使用 WAS6.1 作为服务器。在一个典型的中小客户和大型企业使用 Web Service 进行 B2B 对接的场景中,中小型客户需要使用手中仅有的 standalone 的 java 程序作为客户端,来调用大型企业安全的 Web Service。对于这种 standalone 的 java 客户端,需要一种简单可行的方式来满足 WS-Security。WAS 的开发工具 AST(Application Server Toolkit)6.1.1.3 以及 Rational Application Developer 7.0(需要安装 Web Service Feature Pack)中加入了这样的功能,通过与服务器端类似的策略集配置使得客户端也能保证 Web Service 的 QoS,其中包含 WS-Security。

本文通过一个例子来构建满足 WS-Security 的 Web Service 客户端,并且这个客户端不依赖于任何服务器或 Web 容器,运行在 J2SE 单机环境中。本文首先给出了一个 Web Service 示例服务的 WSDL,描述一个 Web Service 的服务器提供的一个 Web 服务,接下来详细介绍使用 AST 构建这个安全的 standalone 的 Web Service 客户端的步骤,最后说明详细的测试方法,包括使用 TCP/IP 监视器来监控测试报文。

术语说明

  • WAS6.1 本文特指安装了 Web Service Feature Pack 的 WebSphere Application Server 6.1;
  • 客户端本文特指不依赖任何应用服务器或 Web 容器的 Web Service 消费者,运行在 J2SE 单机环境中

WSDL

Web Service 客户端通过服务端的 Web 服务描述语言(WSDL)来获取 Web Service 提供者的接口信息,并且使用这个描述语言来构建客户端的文件。本文使用了如下的 WSDL 来描述服务器端的接口。


清单 1. WSDL


 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


此服务描述语言描述了服务器端提供了一个回声的 Web Service,它有一个字符串格式的输入参数,返回值也是一个字符串格式的参数。Web Service 的服务地址为 http://localhost:9095/EchoWeb/Echo。

构建过程

在得到 Web Service 的接口描述 WSDL 之后,我们就可以开始构建我们的安全的 Web Service 客户端了。本文按照以下的构建步骤来描述整个的客户端的开发过程:

  1. 构建所需的 Java 文件:通过 WSDL 生成开发客户端所需的 Java 类;
  2. 编写客户端实现代码:开发 Web Service 客户端的调用逻辑;
  3. 准备客户端密钥库文件:为 WS-Security 所需的签名加密等动作准备密钥;
  4. 配置客户端 WS-Security 策略集:使得 Web Service 客户端满足 WS-Security 的规范。

构建所需的 Java 文件

wsimport 工具用来从 WSDL 创建 Web Service 所需要的 Java 类文件,包括 JAXB 辅助类和 service 代理类,此工具可以在 \AppServer\bin 下找到。


清单 2. 使用 wsimport 生成 Web Service 所需类文件
wsimport –keep –verbose –p ws.client.echo –wsdllocation file:/c:/wsclient/Echo.wsdl \
Echo.wsdl

主要选项说明:

  • -keep 保留生成的 Java 源文件,否则只有 class 字节码文件;
  • -verbose 在命令行显示生成的 Java 源文件;
  • -p 指定生成的 Java 包选项,即源文件的 import 值,并按照选项后面的参数生成目录结构,将生成文件置于此目录中;
  • -wsdllocation 用来指定使用的 WSDL 的具体位置,这个值会写在生成的 Service 实现类里,Service 实现类将从这个位置来获取 WSDL;

生成的类文件:

  • ws\client\echo\Echo.java Web Service 端点接口(Service Endpoint Interface,简称 SEI),包含服务方法签名;
  • ws\client\echo\Echo_Service.java JAXWS 生成的 javax.xml.ws.Service 的实现,包含 WSDL 信息,用来生成 SEI 实现
  • ws\client\echo\EchoHello.java JAXB 对象,对应 SOAP 消息中的 EchoHello 元素;
  • ws\client\echo\ObjectFactory.java 创建 EchoHello 和 RequestEcho 的工厂类;
  • ws\client\echo\package-info.java 包含命名空间和包信息;
  • ws\client\echo\RequestEcho.java JAXB 对象,对应 SOAP 消息中的 RequestEcho 元素。

编写客户端实现

打开 AST6.1.1.3 的一个工作空间,创建一个 Java 项目:EchoClientStandalone,将前面生成的文件拷贝至 ws.client.echo 包中。

在这个包中创建类 Echo_Client 作为 Web Service 客户端实现,在代码中我们需要做四件事情:

  • 创建 Service 对象,即生成的 Echo_Service;
  • 使用 Service 对象得到 SEI 实现;
  • 设置 soapaction 上下文;
  • 使用 SEI 实现对象调用服务。

清单 3. Echo_Client
package ws.client.echo;

import java.util.Map;

import javax.xml.ws.BindingProvider;


public class Echo_Client {
	// 创建 Service 对象
static Echo_Service service = new Echo_Service();
	public void callService(String req){
		try{
		// 获取 SEI 实现类
		Echo port = service.getEchoSOAP();
		// 设置 soapaction 上下文
 Map context = ((BindingProvider)port).getRequestContext();
		context.put("javax.xml.ws.soap.http.soapaction.uri",\
		"http://www.example.org/Echo/NewOperation");
		// 使用 SEI 实现对象调用服务
System.out.println("before call Echo.requestEcho()");
		System.out.println(port.requestEcho(req));
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}

	public static void main(String[] args){
		Echo_Client client = new Echo_Client();
		String req = " " + args[0];
		client.callService(req);
	}
}


编译不通过,会提示出错。将 \AppServer\plugins\ 目录下的 com.ibm.jaxws.tools_6.1.0.jar 添加到项目的构建路径中。

准备客户端密钥库文件

Web Service 客户端的密钥库文件可以是 p12 或者 JKS 格式。WS-Security 默认采用了非对称加密的机制,因此客户端密钥库文件中应该包含客户端的私钥,用于对出站的 SOAP 报文进行数字签名以及对入站的 SOAP 响应报文进行解密,还应该包含 Web Service 提供者的公钥,用于对出站的 SOAP 报文进行加密以及对入站的 SOAP 响应报文进行数字签名验证。使用 ikeyman 工具(位于 \AppServer\bin\ 目录下)创建两个密钥库文件,具体步骤是:

  1. 打开 ikeyman 工具,选择”Key Database File”,选择”Key database type”为”PKCS12”,在”File Name”后面输入”client_KeyStroe.p12”,见图 1,选择 OK,并在后面的提示框中输入密码。

    图 1. 创建密钥库


  2. 在”Key database content”下面的下拉列表中选择”Personal Certificates”,在菜单中选择”Create->New Self-Signed Certificate…”创建自签署证书,见图 2,在弹出框中填入证书的 标签等信息。



    图 2. 创建自签署证书


  3. 在”Personal Certificates”下,选中新创建的自签署证书,选择右边的”Exprot/Import…”按钮,将证书的公钥导出,供服务器端使用。
  4. 按照步骤 1,新建一个叫做 server_cert.p12 的证书库,在”Key database content”下面的下拉列表中选择”Signer Certificates”,选择右边的”Add…”按钮将服务器导出的公钥(Base64 编码的 ASCII 数据类型或者二进制 DER 数据类型)添加进此证书库。

配置客户端策略集

针对于 WAS 6.1 提供的 Web Service 策略集,AST6.1.1.3 提供了一种在客户端应用程序中通过配置来完成的对应的客户端策略集。这些策略集不改动客户端的源代码,提供了与服务器端对应的 Web Service 服务质量的保证,使得没有应用服务器或者 Web 容器环境下的客户端能够调用有服务质量要求的 Web Service。下面的章节主要描述配置客户端的 WS-Security 策略集。

  1. 在 AST 中选择”File->New->Other”,在弹出的对话框中,选择 Web Services/Policy Set/ 目录下的”Client Side Policy Set Attachment”,点击”Next”按钮。
  2. 在”Client Side Policy Set Attachment”对话框中,选择”Client Project”为”EchoClientStandalone”,在 Application 区域中点击”Add…”按钮为服务端点设置策略集,见图 3。

    图 3. 为客户端添加策略集


  3. 在”End Point definition Dialog”中,为应用程序选择相应的 Service Name,Endpoint,Operation Name。为”Policy Set”选择”WSSecurity default”,在”Binding”后面输入任意绑定名称,此处为”WSS-Binding-Test”,单击”OK”按钮,见图 4。

    图 4. 配置服务端点,策略集和绑定


  4. 回到”Client Side Policy Set Attachment”对话框中,在”Bindings Configuration”下面出现了两个条目”WSSecurity”和”WSAddressing”,后者不需要配置绑定。选择”WSSecurity”,单击下面的”Configure…”按钮,出现”Binding Configuration Dialog”对话框,见图 5。

    图 5. 配置绑定对话框,数字签名配置


  5. 配置出站数字签名。在”Binding Configuration Dialog”中,当前是”Digital Signature Configuration”页,”Outbound Message Security Configuration”下面选的”Key Information Type”,选择”X509ISSUER”,点击”Key Store Settings…”按钮,在”Key Store Setting Dialog”中填入准备密钥库时步骤 1、2 所创建的包含自签署证书(客户端私钥)的证书库信息,如图 6,其中 Key Alias 就是证书的标签。

    图 6. 配置出站签名证书库


  6. 配置入站数字签名验证。回到”Binding Configuration Dialog”,去掉”Inbound Message Security Configuration”下的”Trust Any Certificate”,表明入站的数字签名也需要验证,点击下面的”Key Store Settings…”按钮,在弹出的对话框中填入准备密钥库时步骤 4 所创建的密钥库(包含服务器公钥)相关信息,如图 7。

    图 7. 配置入站签名验证库


  7. 配置出站加密证书。回到”Binding Configuration Dialog”,选择”XML Encryption Configuration”页,”Outbound Message Security Configuration”下面选的”Key Information Type”,选择”X509ISSUER”,点击”Key Store Settings…”按钮,在”Key Store Setting Dialog”中填入准备密钥库时步骤 4 所创建的密钥库(包含服务器公钥)相关信息,如图 8,其中 Key Alias 就是证书的标签。

    图 8. 配置出站加密证书库


  8. 配置入站解密证书。回到”Binding Configuration Dialog”,在”Inbound Message Security Configuration”下选择”Key Store Settings…”按钮,在”Key Store Setting Dialog”中填入准备密钥库时步骤 1、2 所创建的包含自签署证书(客户端私钥)的证书库信息,如图 6,其中 Key Alias 就是证书的标签。
  9. 单击”OK”,回到 Client Side Policy Set Attachment”对话框,选择”Finish”,完成配置,在项目下面可以看到生成了一个 META-INF 文件夹其中包含 Policy Sets 和 WSS-Binding-Test 文件夹以及相关的策略配置,如图 9.

    图 9. 生成的策略文件


测试

在 AST 中,选择文件 -> 导出 ->Jar,选择工程 EchoClientStandalone,导出的 jar 包名称为 EchoClient2Standalone.jar。

编写一个 .bat 批处理文件,设置运行客户端所需的 Classpath。其中,需要有 com.ibm.jaxws.thinclient_6.1.0.jar,此 jar 包可以在 /AppServer/runtime/ 下面找到。wsjaas_client.conf 可以在 /AppServer/profiles//properties/ 目录中找到。见清单 4。


清单 4. 客户端运行批处理文件
@echo off

if %1x == x goto USAGE

:# WAS_HOME is required 
if NOT "%WAS_HOME%" == "" goto HOMEOK
 SET CUR_DIR=%cd%
:HOMEOK
setlocal

set JAASLOGIN=-Djava.security.auth.login.config=%CUR_DIR%\wsjaas_client.conf

:# Edit the lines below if your machine has products installed to different paths
set JAVA_HOME=C:\IBM\Java50\jre
set PATH=%JAVA_HOME%\bin;%PATH%
set CLASSPATH=%CUR_DIR%\com.ibm.jaxws.thinclient_6.1.0.jar;\
%CUR_DIR%\EchoClient2Standalone.jar;.;

:# 
java %JAASLOGIN% -cp "%CLASSPATH%" ws.client.echo.Echo_Client %1
goto END
###################################
:USAGE
@echo The program takes 1 parameters as described below
@echo "USAGE : runEchoClient "
@echo "SAMPLE: runEchoClient hello"
goto END
:END

在运行客户端的时候,运行此客户端需要 IBM jre 5.0(或者更高版本),可以使用 WAS 6.1 下的 jre 来运行。

在运行客户端之前,我们在 AST 中打开附带的 TCP/IP Monitor 来监控报文。假设 Web Service 服务端提供的服务端口是 9085,在 AST 中选择窗口 -> 显示视图 -> 其他 -> 调试 ->TCP/IP 监视器,新建一个 TCP/IP 监视器并填入参入,如图 10。


图 10. 创建 TCP/IP 监视器

在构建客户端之前,确保此 Web Service 服务端已经部署到 WAS6.1 上,并且正确配置了 WS-Security 策略集,保证其正在运行中。

将 EchoClient2Standalone.jar,com.ibm.jaxws.thinclient_6.1.0.jar,以及运行客户端的批处理文件放置于同一个目录,运行批处理文件,查看运行结果,见图 11。


图 11. 运行结果

查看 TCP/IP 监视器。从客户端发向服务器端的 SOAP 信封,经过客户端 WS-Security 策略集的加密和签名,见清单 5。


清单 5. 客户端发向服务器端的 SOAP 信封




MIIBvT...BnesE0=




hS6nfYE9axFgay+gorMEo0I4GfY=




OULe5mAxLwYibommo1Ui/...1gvtagYQ=









TnqRmYse3nLjO+cw14f7...20C1MzPPA==



2008-07-10T09:21:29.875Z



http://9.186.110.205:9095/EchoWeb/Echo

urn:uuid:CD3CB273ED6FC2523A1215681690036

http://www.example.org/Echo/NewOperation





hrGbauq8Y7CefUCqZoZtYy6q0.../3pqVpOs=





服务器端解密并验证之后,接受了客户端的 SOAP 信封。从服务器端返回的 SOAP 信封,经过了服务器端 WS-Security 策略集的加密和签名,被 TCP/IP 监视器捕获到,见清单 6。


清单 6. 服务器端返回的 SOAP 信封




MIIBvTCCA...6qBnesE0=
MIIBvTCCA...4QsyJ3IM=








P3o2ROBqCC...WT8zbKkXSzk0=









gWuUf6RbFmaL8h1TS/yv.../JvVe40LQ3S



2008-07-10T09:19:17.578Z



http://www.example.org/Echo/Echo/requestEchoResponse

urn:uuid:CD3CB273ED6FC2523A1215681690036





o1ATY1fu4L4GvlNqjUvIADJ...iTXScQZY4=





结束语

满足 WS-Security 的 Web Service 服务端需要同样满足 WS-Security 的客户端来进行调用。对于一个在 WAS6.1 环境下的 Web Service 客户端(一个 J2EE 应用),应用服务器提供了针对 WS-Security 的 QoS 支持。针对运行时为单机 J2SE 的 Web Service 客户端的情况,本文通过一个实例展示了如何使用 AST 构建这样的一个不依赖于应用服务器或者 Web 容器的 Standalone 的 JAX-WS Web Service 客户端,并且此客户端符合 WS-Security 标准,能够调用满足 WS-Security 的服务端提供的 Web 服务,进行安全的交互。除了 WS-Security,AST 还提供其他的策略集支持,包括 LTPA RAMP,SecureConversation,WSAddressing,WSHTTPS,WSReliableMessaging,WSTransaction 等,能够满足 WAS 服务器端的各种服务质量的要求。

请使用浏览器的分享功能分享到微信等