内容


Web 服务 SOAP 消息验证

使用 Web Services Validation Tool for WSDL and SOAP

Comments

引言

随着诸如 XML 和 HTTP 等新技术和标准的出现,似乎 Web 服务成为了互联网创新聚集地。但是这些创新来源于哪里呢?

Web 服务的基本概念可以追溯到美国 60 年代中期。运输行业,如铁路和运输公司,提出了一个新的计算机之间的电子数据交换概念,它后来发展成为 Electronic Data Interchange (EDI)。我是在 80 年代从一位商业学校教授那里第一次听说 EDI 的。

在 1996 年,U.S. National Institute of Standards and Technology 在 Federal Information Processing Standards Publications (FIPS PUB 161-2) 中发布了 Electronic Data Interchange (EDI) 标准。根据所发布的标准,EDI 是计算机到计算机的严格的消息交换格式。接收的消息是只通过计算机处理,并且一般不需要人工解释。这其实就是 Web 服务所实现的功能,只不过 60 年代还没有 XML、Internet 和 World Wide Web。

考虑到有些读者还不熟悉 Web 服务,我首先简单地总结一下 Web 服务的定义和主要组件。

什么是 Web 服务?

一个 Web 服务是使用 World Wide Web Consortium 定义的 Simple Object Access Protocol (SOAP) 在网络上的计算资源之间支持互通的计算机到计算机交互的一个软件系统。

Simple Object Access Protocol (SOAP) 一个简单且可扩展的协议,使用它构造和定义的消息可以在分散和分布式的网络环境中交换。SOAP 消息的格式是由 Extensible Markup Language (XML) 定义的,XML 是一种简单灵活的文件格式,它来源于 Standard Generalized Markup Language (SGML),这种语言是由 International Organization for Standardization (ISO 8879:1986) 开发的。

Web Services Description Language (WSDL) 是基于 XML 的语言,它是一个描述 Web 服务的接口。

如果交换的 SOAP 消息是错误会导致什么后果?如果不小心处理的是错误的 SOAP 消息,或者用错误的 SOAP 消息生成决策信息,又会导致什么后果?

实际上,您是无法知道一个 SOAP 消息中的数据是否正确。您至少可以通过查找它的接口定义,或 WSDL 来检查一个 SOAP 消息是否有效。

事实上,调试 SOAP 消息中的问题是很困难的。如果一个 SOAP 消息中有错误,您将会从 Web 服务服务器得到一个 HTTP 响应码:500。Web 服务服务器不会详细地告诉您 SOAP 消息的哪个部分出了错误。您还可能遇到更糟糕的情况,那就是您从 Web 服务服务器接收到没有任何错误消息的有效的 SOAP 响应消息,而且您和 Web 服务服务器都没有发现您的 SOAP 请求消息和 SOAP 响应消息出现问题。例如,您在一个特定时间请求查询公司 B 的股票价格,但是您写错了标签,并发送一个 SOAP 消息到一个 Web 服务服务器。这个 Web 服务服务器可能发现不了这个拼写错误的标准,而在 SOAP 响应消息中返回给您一个默认值,如公司 A 股票价格。如果没有发现这个问题,这可能会导致严重的后果。

您可以使用 Web Services Validation Tool for WSDL and SOAP 预先防止这类问题的出现。您可以使用 Web Service Definition Language (WSDL) 在 Web 服务应用部署之前对 SOAP 消息进行验证。这个工具将会使用 WSDL 分析、解析、验证您的 SOAP 消息,然后用详细的错误消息和代码行号标识问题。而不是使用 HTTP 响应代码:500。如果 SOAP 消息是加密的呢?那也一样有效。这个工具能够将消息解密,然后为您验证解密后的 SOAP 消息。

这个工具已经被用于帮助 IBM Web 服务支持团队解决全世界客户报告的 IBM® WebSphere Application Server 上与 Web 服务相关的问题。如果您的 SOAP 消息是加密的,它也能够将消息解密,并验证解密后的消息。如果您的 SOAP 消息带有数字签名,它将会帮您验证这个签名。您甚至可以使用 Web Services Validation Tool for WSDL and SOAP 发送 SOAP 消息到 Web 服务服务器并接收响应的 SOAP 消息。这个工具在开发早期可用于有效避免生产环境问题,并减少处理生产环境中出现的问题的时间。

我们将创建一个非常简单的 Web 服务。首先我们将创建一个简单的 Java™ 应用。在我们验证这个 Java 应用正常工作后,我们将使用 IBM Rational® Application Developer for WebSphere® Software 生成一个 Web 服务。然后我们将修改所生成的 Web 服务。最后我们将使用 Web Services Validation Tool for WSDL and SOAP 创建、验证、传输和接收 SOAP 消息。

您可以使用 IBM Rational Application Developer for WebSphere Software 创建一个简单的 Web 服务。Web 服务可以通过两种方法创建:

  1. 使用自上而下的开发方式从一个 WSDL 生成 Web 服务 Java™ 实现类。
  2. 使用自下而上的开发方式从一个 Java Bean 或企业 Java Bean 生成一个 Web 服务。

下面的例子将会介绍使用自下而上的开发方法实现一个 Web 服务。您将首先创建一个简单的 Java 应用。然后,您将使用 IBM Rational Application Developer for WebSphere Software 从 Java 应用中生成一个自下而上的 Java Bean Web 服务。

创建一个 Java 应用

首先,您将创建一个欢迎您的 Java 应用。如果您没有输入您的名字,这个应用将会返回 “Hello, buddy!”。如果输入了您的名字,这个应用会返回 “Hello,”,后面是您的名字。下面是这个 demo 包的 Java 应用 DemoWebService。函数 hello() 会返回一个包含您名字的字符串。

清单 1. DemoWebService.java
 /*
 * @author: Jinwoo Hwang
 * Copyright 2010 IBM Corporation
 */

package demo;

public class DemoWebService {
	public String hello(String name) {
		if (name == null)
			return "Hello, buddy!";
		else
			return "Hello, " + name + "!";
	}
}

测试 Java 应用

在您从 Java 应用创建一个 Web 服务器之前,测试这个 Java 应用是很重要的。您可以编写一个带有 main() 函数的类来运行这个应用。您可以使用 IBM Rational Application Developer v7 所提供的 Universal Test Client, 不需要编写代码就能快速地测试应用。您所需要做的就是从 Java 类的上下文菜单中单击 Universal Test Client 启动这个 Test Client。

  1. 在 Universal Test Client 中,展开 Objects > DemoWebService
  2. 选择函数 hello
  3. 输入一个字符串或您的名字到 Value 域,然后单击 Invoke
图 1. Universal Test Client
Universal Test Client
Universal Test Client

您也可以使用一个空值参数来测试,看结果是什么。如果传递一个空值参数到函数 hello() 中,正常情况它会返回 “Hello, buddy!”。

图 2. 使用空值参数的 Universal Test Client
使用空值参数的 Universal Test Client
使用空值参数的 Universal Test Client

创建一个 Web 服务

一切都正常运行了。现在您可以使用自下而上的 Web 服务开发方法从 Java 类生成一个 Web 服务。

  1. 选择这个 Java 应用 DemoWebService,然后从 IBM Rational Application Developer 创建一个新的 Web 服务。
图 3. 创建一个新的 XML Web 服务
创建一个新的 XML Web 服务
创建一个新的 XML Web 服务
  1. 在您创建了一个 Java 类后,选择 Bottom up Java bean Web service 作为 Web 服务类型。选择 Start client,然后单击 Finish。如果您有 Java Enterprise bean (EJB) 类,您也可以创建一个 EJB 来生成一个 Web 服务。
图 4. 选择一个服务实现
选择一个服务实现
选择一个服务实现

如果所有步骤正确,您将会发现 Java Resources 中 DemoWebService.java 后面会生成一个 DemoWebServiceDelegate.java。

图 5. DemoWebService.java
DemoWebService.java
DemoWebService.java

如果查看 DemoWebServiceDelegate.java,您会发现一个 Java Web 服务注释 @javax.jws.WebService,这个注释在类 DemoWebServiceDelegate 中指定了 targetNamespace、serviceName 和 portName。其中创建了一个 DemoWebService 实例,从 DemoWebService 的 hello() 函数定义了另一个 hello()。如果您想了解更多关于 Java Web 服务注释的说明,请参考 Java Specification Request(JSR) 181:Web Services Metadata for the Java Platform。

清单 2. DemoWebServiceDelegate.java
/*
 * @author: Jinwoo Hwang
 * Copyright 2010 IBM Corporation
 */
package demo;

@javax.jws.WebService(targetNamespace = "http://demo/", 
        serviceName = "DemoWebServiceService", 
        portName = "DemoWebServicePort")
public class DemoWebServiceDelegate {

	demo.DemoWebService _demoWebService = new demo.DemoWebService();

	public String hello(String name) {
		return _demoWebService.hello(name);
	}

}

创建一个 WSDL

在客户端项目中,您也会发现其中生成了 DemoWebServiceService.wsdl 和 DemoWebServiceService_schema1.xsd。DemoWebServiceService.wsdl 包含了描述您之前创建的 Java 应用的网络服务的 Web Service Definition Language。DemoWebServiceService_schema1.xsd 包含了描述 SOAP 消息中使用的日期类型结构的 XML 模式。

图 6. DemoWebServiceService.wsdl
DemoWebServiceService.wsdl
DemoWebServiceService.wsdl

如果查看 DemoWebServiceService.wsdl,您将能够看到它的根元素中有一组定义元素。在定义元素内,我们可以发现以下 6 个元素:

  • types
  • message
  • portType
  • binding
  • service
  • port

Types:定义了消息交换中使用的数据类型。在 DemoWebServiceService.wsdl 中,您可以导入 DemoWebServiceService_schema1.xsd,而不需要在 WSDL 文件中定义数据类型。

Message: 定义了所交换的消息。您有两个消息,“hello” 和 “helloResponse”。消息 hello 其中有一部分是 “parameters”。这个部分有一个元素 “tns:hello”。而消息 helloResponse 其中有一部分是 “parameters”,刚好与 hello 的一样。这个部分有一个元素 “tns:helloResponse”。这两个元素 hello 和 helloResponse 都定义在 DemoWebServiceService_schema1.xsd 中。您很快会下面看到它的内容。

Port Type:支持终端的操作。一个操作会提供一个输入消息和一个输出消息。您有一个名为 “hello” 的操作,它由一个输入消息 “tns:hello” 和一个输出消息 “tns:helloResponse” 组成。这是一个请求-响应传输。一个 WSDL 为终端提供了 4 种不同的传输基本参数:

  • one-way
  • request-response
  • solicit-response
  • notification

在 one-way 传输中,一个终端只能接收消息。在 request-response 传输中,一个终端会先接收一个消息然后再发送一个相应的消息。在 solicit-response 传输中,一个终端会先发送一个消息然后再接收一个相应的消息。在 notification 传输中,一个终端只能发送消息。

Binding:定义了由一种端口类型定义的操作和消息的协议细节和消息格式规范。您会为 style 属性提供一个 “document”。这个 style 属性包含 2 种不同类型的消息,rpc 和 document。如果是 rpc,消息会包含了一些参数和返回值。如果是 document ,消息则包含一些文档。transport 属性的值包含了 SOAP 的传输 URI。http://schemas.xmlsoap.org/soap/http 表示您将使用 SOAP 规范中的 HTTP 绑定。您要为 soapAction 属性中 SOAP 的 HTTP 绑定的 SOAPAction HTTP 头指定 URI。由于您使用了一个 SOAP 的 HTTP 绑定,因此必须指定 soapAction 属性的值。您可以为 soapAction 属性指定一个空字符串,即 ""。soap:body 元素指定了如何在 SOAP 消息主体元素内聚集消息各部分。而 use 属性则提供了两个不同的选项:literal 和 encoded。如果您使用 literal,这表示您使用一个使用元素或类型属性的具体的模式定义。如果您使用 encoded,那么您使用的是带有编码规则的抽象类型。

Service:定义了一组相关的端口。

Port:通过为一个绑定指定一个网络地址而定义一个通信终端。

http://localhost:9081/HelloWorldWSProject/DemoWebServiceService 是 SOAP 终端的地址。

清单 3. DemoWebServiceService.wsdl
<?xml version="1.0" encoding="UTF-8"?> 
<definitions name="DemoWebServiceService" targetNamespace="http://demo/"
	xmlns="http://schemas.xmlsoap.org/wsdl/" 
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
	xmlns:tns="http://demo/" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<types>
		<xsd:schema>
			<xsd:import namespace="http://demo/" 
                schemaLocation="DemoWebServiceService_schema1.xsd" />
		</xsd:schema>
	</types>
	<message name="hello">
		<part element="tns:hello" name="parameters" />
	</message>
	<message name="helloResponse">
		<part element="tns:helloResponse" name="parameters" />
	</message>
	<portType name="DemoWebServiceDelegate">
		<operation name="hello">
			<input message="tns:hello" />
			<output message="tns:helloResponse" />
		</operation>
	</portType>
	<binding name="DemoWebServicePortBinding" type="tns:DemoWebServiceDelegate">
		<soap:binding style="document"
			transport="http://schemas.xmlsoap.org/soap/http" />
		<operation name="hello">
			<soap:operation soapAction="" />
			<input>
				<soap:body use="literal" />
			</input>
			<output>
				<soap:body use="literal" />
			</output>
		</operation>
	</binding>
	<service name="DemoWebServiceService">
		<port binding="tns:DemoWebServicePortBinding" name="DemoWebServicePort">
			<soap:address
				location=
                "http://localhost:9081/HelloWorldWSProject/DemoWebServiceService" />
		</port>
	</service>
</definitions>

创建一个模式

您是从 DemoWebServiceService.wsdl 导入 DemoWebServiceService_schema1.xsd 的。现在查看 DemoWebServiceService_schema1.xsd 的内容。它是使用 XML 模式定义语言编写的,描述了 XML 文档的内容结构和约束。您拥有两个元素,分别是 hello 和 helloResponse。每一个元素都有一个对应的类型。其中 hello 类型有一个元素 “arg0”,它是一个字符串。元素 “arg0” 是可选的,因为 minOccurs 属性的值声明为 0。如果 minOccurs 属性值是 1 或以上,就一定要包含一个元素。类型 helloResponse 中的元素 “return” 的情况是一样的。

清单 4. DemoWebServiceService_schema1.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema targetNamespace="http://demo/" version="1.0"
	xmlns:tns="http://demo/" xmlns:xs="http://www.w3.org/2001/XMLSchema">

	<xs:element name="hello" type="tns:hello" />

	<xs:element name="helloResponse" type="tns:helloResponse" />

	<xs:complexType name="hello">
		<xs:sequence>
			<xs:element minOccurs="0" name="arg0" type="xs:string" />
		</xs:sequence>
	</xs:complexType>

	<xs:complexType name="helloResponse">
		<xs:sequence>
			<xs:element minOccurs="0" name="return" type="xs:string" />
		</xs:sequence>
	</xs:complexType>
</xs:schema>

启动 Web Services Validation Tool for WSDL and SOAP

现在,您已经了解了 WSDL 和模式。下面,要启动 Web 服务服务器,这样您就可以从 Web Services Validation Tool for WSDL and SOAP 中调用 Web 服务了。

为了运行 Web Services Validation Tool for WSDL and SOAP,您需要安装 Java 6(或以上)运行环境和 XML 数据加密和解密 API,这个 API 是基于 World Wide Web Consortium 的 XML Encryption Syntax 和处理规范(http://www.w3.org/TR/xmlenc-core/)的。

IBM Java 6 提供了 JSR 106 的实现:XML Digital Encryption API。如果您安装了 IBM Java 6,您就可以直接进行下一步而不需要安装任何东西。

如果您安装了 Java 6 运行环境,如 Sun Microsystems™ Java 6,而它不包含 XML Digital Encryption API,那么您需要安装实现了 JSR 106 或 Apache™ XML Security version 1.4.3(http://santuario.apache.org/)的程序库。您可以只下载二进制文件,将它解压缩到一个目录,然后使用 –vmargs 和 –DAXS 命令行选项告诉工具目录的路径。

在本文撰写时,Web Services Validation Tool for WSDL and SOAP 支持使用 JSR 106 和 Apache XML Security version 1.4.3 进行 XML 数字加密和解密。如果您希望验证 SOAP 消息中的数字签名,您需要实现 JSR 105 的程序库:XML Digital Signature APIs。幸好,Sun Microsystems 和 IBM 所提供的 Java 6 虚拟机都实现了 JSR 105。这就是为什么选择 Java 6 作为 Java 运行环境的最低要求。如果您的 Java 6 不包含实现 JSR 105 的程序库,您需要查找支持 JSR 105 的程序库。

您可以从 http://www.alphaworks.ibm.com/tech/wsvt 免费下载 Web Services Validation Tool for WSDL and SOAP。工具的安装很简单。解压缩程序包到一个目录,然后运行 wsvt.exe。如果您的默认 Java 虚拟机不是支持 XML 数字签名和数字加密及解密的 Java 6,您需要通过选项 -vm 指定 Java 6 的路径,例如:

wsvt –vm c:\IBMjava6\bin\java.exe

再一次,如果您安装了 IBM Java 6,您就不需要再安装任何程序了。您所需要的所有程序都包含在 IBM Java 6 中。如果安装的是 Sun Microsystems 的 Java 6,您就需要让工具知道 Apache XML Security 的位置,从而支持 SOAP 消息的加密和解密。

例如,下面的命令将会使用 Sun Java 6 和 Apache XML Security version 1.4.3 启动工具,这位于目录 C:\xml-security-1_4_3\libs:wsvt –vm c:\SUNjava6\bin\java.exe –vmargs –DAXS=C:\xml-security-1_4_3\libs

虽然 Apache XML security version 1.4.3 有 9 个 jar 文件,但是只有下面的 jar 文件是 Web Services Validation Tool for WSDL and SOAP 实际使用的 Apache XML Security 库文件:
commons-logging.jar
serializer.jar
xalan.jar
xmlsec-1.4.3.jar

在 Web Services Validation Tool for WSDL and SOAP 的 MANIFEST.MF 文件中,我们可以找到:
Bundle-ActivationPolicy: lazy
Bundle-ClassPath: .,
external:$AXS$/commons-logging.jar,
external:$AXS$/serializer.jar,
external:$AXS$/xalan.jar,
external:$AXS$/xmlsec-1.4.3.jar

这就是为什么您需要为 Sun Java 6 环境指定参数 –vmargs –DAXS=C:\xml-security-1_4_3\libs 以便对消息进行加密和解密的原因所在。

我曾经花费很长时间解决 Sun Java 运行环境、Apache XML Security 和一些 Eclipse 插件中与 XML 相关的类的类加载冲突和不兼容问题。IBM Java 运行环境则很好用,因为它带有了 JSR 106 实现,它不需要使用 Apache XML Security。

创建一个项目

接下来,当工具启动和运行后,您就可以创建一个新的项目了。您的项目中可能有一个 WSDL 文件,与这个 WSDL 文件相关的多个模式文件,以及 XML 文件中的 SOAP 消息。如果项目中有多个 WSDL 文件,只有 1 个 WSDL 文件会被使用,而其他的 WSDL 会在验证SOAP 消息 XML 文件时被忽略。您需要创建一个单独的项目来使用其他的 WSDL 文件。每一个 SOAP 消息都应该存储在一个扩展名为 .xml 的文件中。否则它不会被作为一个 SOAP 消息使用。

  1. 右键单击,选择 New > Project 创建一个新项目。
图 7. 创建一个新项目
创建一个新项目
创建一个新项目
  1. 选择 General 下的 Project
图 8. 选择一个向导
选择一个向导
选择一个向导
  1. Project name 中输入 “Test Project”,然后单击 Finish
图 9. 项目名称
项目名称
项目名称

导入一个 WSDL 和一个模式

您已经创建了一个项目 “Test Project”。现在您可以将 WSDL 和 XSD 导入到这个项目中。

  1. 选择项目并单击上下文菜单的 Import
图 10. 导入
导入
导入
  1. 选择 General 下的 File System
图 11. 选择导入来源
选择导入来源
选择导入来源
  1. 选择 WSDL 和 XSD 存储的目录。
  2. 选择两个文件(DemoWebServiceService.wsdl 和 DemoWebServiceService_schema1.xsd),然后单击 Finish
图 12. 从文件系统导入
从文件系统导入
从文件系统导入

查看 WSDL 和模式

现在您的项目包含了 WSDL 和 XSD。您可以双击 WSDL 以设计模式和源代码模式查看 WSDL。在设计模式中,您可以可视化编辑 Web 服务的输入和输出。

图 13. 设计模式
设计模式
设计模式

在源代码模式,您可以在一个文本编辑器中查看和编辑 WSDL。

图 14. 源代码模式
源代码模式
源代码模式

如果您无法使用一个 XSD 编辑器打开 XSD 文件,您可以通过选择 XSD 文件的上下文菜单中选择 Open With > XML Editor 使用一个 XML 编辑器打开 XSD 文件。

图 15. 打开 XML 编辑器
打开 XML 编辑器
打开 XML 编辑器

您使用 XML 编辑器打开 DemoWebServiceService_schema1.xsd。

图 16. XML 编辑器
图 16. XML 编辑器
图 16. XML 编辑器

创建一个 SOAP 消息

您已经有了可用于验证 SOAP 消息的 WSDL 和模式。现在可以使用 Web Services Validation Tool for WSDL and SOAP 测试一个 SOAP 消息了。您需要在项目中创建一个 SOAP 消息。这个 SOAP 消息应该保存在一个扩展名为 .xml 的文件中。

  1. 选择 New > XML,在项目中创建一个 SOAP 消息。
图 17. 新的 XML
新的 XML
新的 XML
  1. 选择一个新 SOAP 消息的上级文件夹 Test Project。如果还没有选择,在 File name 域中输入 “DemoSOAPMessage.xml”,并单击 Finish
图 18. 输入上级文件夹
输入上级文件夹
输入上级文件夹

这个工具会自动使用 XML 编辑器打开一个新的 XML 文件。新建的 XML 文件中只包含一行包含 XML 版本和 XML 编码方式的代码。至少在您从零开始创建一个 SOAP 消息之前已经有这样一行代码。您还不知道如何编写一个 SOAP 消息?下一部分您将了解创建一个 SOAP 消息的详细步骤。

图 19. 新的 XML 文件
新的 XML 文件
新的 XML 文件

要创建一个 SOAP 消息,您可以使用一个值为我的名字 “Jinwoo” 的参数 “parameters” 调用服务 “hello”。当然,您也可以使用您的名字。您要使用名称空间 “http://demo/”。要注意,它是 “http://demo/” 而不是 “http://demo”。没错,这两者区别很大。

清单 5. HelloWorldSOAPmessage.xml
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:ns0="http://demo/">
	<soapenv:Body>
		<ns0:hello>
			<parameters>Jinwoo</parameters>
		</ns0:hello>
	</soapenv:Body>
</soapenv:Envelope>

您发现这个 SOAP 消息中的问题了吗?如果您的确发现了问题,不用担心。本文将在稍后解决其中的问题。

图 20. DemoSOAPMessage.xml
DemoSOAPMessage.xml
DemoSOAPMessage.xml

发送一个 SOAP 消息

您已经作好发送消息到 Web 服务服务器的准备了吗?

  1. 在 Web Services Validation Tool for WSDL and SOAP 中选择这个 SOAP 消息,然后单击 Transmit SOAP Request and Receive SOAP Response
图 21. 发送 SOAP 请求和接收 SOAP 响应
发送 SOAP 请求和接收 SOAP 响应
发送 SOAP 请求和接收 SOAP 响应
  1. 在 Transmit SOAP Request and Receive SOAP Response 窗口中,您可以填写 Service Address、SOAPAction 和 Content-Type。在这个应用中您不需要使用 SOAPAction,因为您在 DemoWebServiceService.wsdl 的绑定部分的 soapAction 属性使用的是一个空字符串 ""。
  2. 如果服务器位于 localhost:9081,那么要在 Service Address 中填写 http://localhost:9081/HelloWorldWSProject/DemoWebServiceService。否则,您需要填写可以访问 Web 服务的一个正确地址。
  3. 选择 text/html 作为 Content-Type
  4. 单击 OK 将这个 SOAP 消息发送到服务器上。
图 22. 输入服务器和目标地址
输入服务器和目标地址
输入服务器和目标地址

接收一个 SOAP 消息

如果服务器已经启动和运行,您应该就能接收到一个 SOAP 响应。如果您没有接收到任何响应,那么要确认您填写的地址和内容类型是正确的。

图 23. 响应
响应
响应

验证 SOAP 消息

很好。您已经接收到一个 SOAP 响应了。而且它会被保存到项目中。但是,您是否发现有什么不对了?您得到的响应是 “Hello, buddy!” 而不是 “Hello, Jinwoo!”。为什么错了?您知道原因吗?

可惜,Web 服务并没有告诉您错误是如何发生的。没有任何错误消息。也没有任何警告消息。如果返回的 SOAP 响应是不正确而 Web 服务服务器却没有报告这个 SOAP 消息错误,那么这种情况会很棘手了。

Web Services Validation Tool for WSDL and SOAP 会帮您查出错误的原因。

清单 6. 响应
<?xml version="1.0" encoding="UTF-8"?>
        <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns2:helloResponse xmlns:ns2="http://demo/">
      <return>Hello, buddy!</return>
    </ns2:helloResponse>
  </soapenv:Body>
</soapenv:Envelope>

下面的步骤将介绍如何验证 DemoSOAPMessage.xml 文件,以查看请求的 SOAP 消息中是否有问题。

  1. 选择请求 SOAP 消息,然后单击 Validate
图 24. 验证请求 SOAP 消息
验证请求 SOAP 消息
验证请求 SOAP 消息

Web Services Validation Tool for WSDL and SOAP 发现 SOAP 消息中的错误。

Invalid SOAP message:cvc-complex-type.2.4.a:Invalid
content was found starting with element 'parameters'. One of '{arg0} is expected.
图 25. 无效的 SOAP 消息
无效的 SOAP 消息
无效的 SOAP 消息

编辑一个 SOAP 消息

  1. 工具报告 “parameters” 有错误。您需要将它修改为 arg0,然后保存。
清单 7. 编辑 SOAP 消息
<?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
        xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	
        xmlns:ns0="http://demo/">
	<soapenv:Body>
		<ns0:hello>
			<arg0>Jinwoo</arg0>
		</ns0:hello>
	</soapenv:Body>
</soapenv:Envelope>
  1. 验证所修改的 SOAP 请求消息。这样您就不会再看到错误的消息了。
图 26. 编辑一个 SOAP 消息
编辑一个 SOAP 消息
编辑一个 SOAP 消息
  1. 您现在可以将修改后的请求消息发送到服务器了。选择这个 SOAP 消息,然后单击 Transmit SOAP Request and Receive SOAP Response
图 27. 发送 SOAP 请求和接收 SOAP 响应
发送 SOAP 请求和接收 SOAP 响应
发送 SOAP 请求和接收 SOAP 响应
  1. Transmit SOAP Request and Receive SOAP Response 窗口中,如果服务器位于 localhost:9081,那么在 Service Address 输入 http://localhost:9081/HelloWorldWSProject/DemoWebServiceService
  2. 选择 text/html 作为 Content-Type,然后单击 OK
图 28. 发送 SOAP 请求
发送 SOAP 请求
发送 SOAP 请求

这次您就能够收到预期的正确响应了。

图 29. 正确的响应
正确的响应
正确的响应
清单 8. SOAP 响应
<?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns2:helloResponse xmlns:ns2="http://demo/">
      <return>Hello, Jinwoo!</return>
    </ns2:helloResponse>
  </soapenv:Body>
</soapenv:Envelope>

删除一个错误的名称空间

如果您发送了一个错误的名称空间,结果会怎么样?

  1. 将名称空间修改为 “http://demo2/”,然后保存。
图 30. 修改名称空间
修改名称空间
修改名称空间
清单 9. 修改名称空间
<?xml version="1.0" encoding="UTF-8"?>
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 	
    xmlns:ns0="http://demo2/">
	<soapenv:Body>
		<ns0:hello>
			<arg0>Jinwoo</arg0>
		</ns0:hello>
	</soapenv:Body>
</soapenv:Envelope>
  1. 然后,您可以再发送请求到服务器。
图 31. 发送消息
发送消息
发送消息

您会得到一个 IOException:服务器对 URI: http://localhost:9081/HelloWorldWSProject/DemoWebServiceService 返回 HTTP 响应代码:500。

图 32. IOException
IOException
IOException

Web 服务服务器虽然返回一个 IOException 响应,但是对于您来说这些信息还不足以查找出问题发生的原因。您需要使用工具验证这个消息,看能否得到能解决这个问题的更好的信息。

图 33. 验证消息
验证消息
验证消息

工具显示 “Invalid SOAP message:cvc-complex-type.2.4.a:Invalid content was found starting with element ‘ns0:hello'. One of '{"http://demo/":hello,"http://demo/":helloResponse}' is expected.”

它指出预期的地址是 “http://demo/”。这是您真正想知道的信息,而不是 HTTP 响应代码 500。

图 34. 无效的 SOAP 消息
无效的 SOAP 消息
无效的 SOAP 消息

验证加密的 SOAP 消息

如果您的 SOAP 消息是加密的,应该如何处理呢?只要您有密钥和密码,这就不是问题。您只需要选择 SOAP 消息,然后单击 Validate,这跟其他 SOAP 消息的操作一样。如果您的 SOAP 消息是加密的,那么工具会弹出类似于下面的对话框:

图 35. 密钥库选择
密钥库选择
密钥库选择

在本文撰写时,它支持 3 种密钥库:

  1. Java Key Store (JKS)
  2. Java Cryptography Extension Key Store (JCEKS)
  3. Personal Information Exchange Syntax Standard (Public Key Cryptography Standards #12)

您需要提供关于您的密钥库的信息:文件名、文件类型和密码。如果这些信息正确,那么您需要选择一个密钥和密码。您也可以看到关于您的密钥库及其中的密钥和证书列表的信息,如密钥库类型、提供者姓名、提供者版本、提供者信息、密钥类型、创建日期、证书类型、算法和格式。

图 36. 密钥选择
密钥选择
密钥选择

如果所有信息都正确,这个工具会生成一个解密的 SOAP 消息,并为您验证这个消息。

图 37. 解密后的 SOAP 消息
解密后的 SOAP 消息
解密后的 SOAP 消息

目前支持的加密算法有以下几种:

  • Cipher Block Chaining (CBC) 中支持初始化向量(128/192/256 位)模式的 Advanced Encryption Standard (AES)
  • Advanced Encryption Standard (AES) Key Encryption (128/192/256 位)
  • Triple Data Encryption Algorithm Modes of Operation (triple-DES) Key Encryption
  • Cipher Block Chaining (CBC) 模式中的 Triple Data Encryption Algorithm Modes of Operation (triple-DES) Key Encryption
  • RSA Cryptography Specifications Version 1.5
  • 支持掩码生成功能的 RSA Optimal Asymmetric Encryption Padding (OAEP) 方法

验证带数字签名的 SOAP 消息

如果您的 SOAP 消息是经过数字签名的,又应该怎么样处理呢?您需要选择这个 SOAP 消息,然后单击 SOAP Message Digital Signature Verification

图 38. SOAP 消息数字签名验证
SOAP 消息数字签名验证
SOAP 消息数字签名验证

如果数字签名是有效的,那么您会看到如下的界面:

图 39. 有效的 SOAP 消息数字签名
有效的 SOAP 消息数字签名
有效的 SOAP 消息数字签名

否则,这个工具会告诉您这个签名是无效的。目前支持的数字签名和规范有以下几种:

  • Secure Hash Algorithm 1 (SHA-1)
  • Hash Message Authentication Code (HMAC)
  • Digital Signature Algorithm (DSA)
  • Public-Key Cryptography Standards (PKCS #1)
  • RSA Encryption Algorithm with Secure Hash Algorithm (SHA-1)
  • Canonical XML Version 1.0 and 1.1
  • XSL Transformations (XSLT) Version 1.0
  • XML Path Language (XPath) Version 1.0
  • Base64

使用一个 SOAP 消息访问 U.S. National Weather Service

您所创建和测试的简单 Web 服务所有方面都运行正确了。那么您是否能够在一个 “实际” 环境中使用这个工具呢?您可以尝试使用 U.S. National Oceanic and Atmospheric Administration (NOAA) 的 National Weather Service 的一个生产环境 Web 服务。

  1. 创建一个项目。
图 40. 创建一个项目
创建一个项目
创建一个项目
  1. 创建一个 SOAP 消息 XML,
图 41. 输入上级文件夹
输入上级文件夹
输入上级文件夹
图 42. 新的 XML 文件
新的 XML 文件
新的 XML 文件

U.S. National Weather Service 会操作 National Digital Forecast Database (NDFD),这个服务可以通过 Simple Object Access Protocol (SOAP) Web Service 进行查询。关于这个服务的详细信息可以参考 http://www.weather.gov/forecasts/xml/

U.S. National Weather 提供了许多不同的 Web 服务。您可以尝试使用一个名为 NDFDgenByDay 的服务,它可以用来查询一个给定经度和纬度的地区的天气预报。

要访问 NDFDgenByDay,您需要提供以下信息:

表 1. NDFDgenByDay
服务名称NDFDgenByDay
Endpoint http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php
SoapAction http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay
encodingStylehttp://schemas.xmlsoap.org/soap/encoding/
Namespacehttp://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl
latitudeDecimal
longitudeDecimal
startDateDate
numDaysInteger
formatString

在这个例子中,您希望创建一个请求 SOAP 消息,查询一个地区(LAT38.9,LON-77.01)从 2010-07-23 开始未来 7 天以 24 小时格式显示的天气预报:

清单 10. 请求 SOAP 消息
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
	<SOAP-ENV:Body>
		<ns6244:NDFDgenByDay>
			<latitude xsi:type="xsd:string">38.99</latitude>
			<longitude xsi:type="xsd:string">-77.01</longitude>
			<startDate xsi:type="xsd:string">2010-07-23</startDate>
			<numDays xsi:type="xsd:string">7</numDays>
			<format xsi:type="xsd:string">24 hourly</format>
		</ns6244:NDFDgenByDay>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

您没有定义名称空间,因为它不需要使用名称空间。如果您遇到名称空间问题,那么一定要定义名称空间。

图 43. 创建 SOAP 名称空间
创建 SOAP 名称空间
创建 SOAP 名称空间

选择这个消息,然后在 Web Services Validation Tool for WSDL and SOAP 中单击 Transmit SOAP Request and Receive SOAP Response

表 2. 请求信息
名称
Endpoint http://www.weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php
SoapAction http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl#NDFDgenByDay
Content-typetext/xml; charset=utf-8
图 44. 发送请求
发送请求
发送请求

您会从 U.S. National Weather Service 获得天气预报数据!但是由于这些数据是用特殊的 HTML 实体表示的,所以它很难读懂。

图 45. 响应消息
响应消息
响应消息

您可以将文件扩展名修改成 .html,就可以在一个 Web 浏览器上查看这些特殊的 HTML 实体。

图 46. 重命名 xml 文件
重命名 xml 文件
重命名 xml 文件
图 47. 新的名称
新的名称
新的名称

然后使用一个 Web 浏览器打开这个 HTML。

图 48. 使用一个 Web 浏览器打开
使用一个 Web 浏览器打开
使用一个 Web 浏览器打开

现在您可以看到 XML 输出了。然而,由于这些内容还没有格式化,所以阅读起来仍然有些问题。

图 49. XML 输出
XML 输出
XML 输出

您可以简单的拷贝这些内容,然后创建一个新的 XML 文档进行格式化。

图 50. 复制 XML
复制 XML
复制 XML

创建一个新的 XML 文件,然后粘贴和格式化。

图 51. 新的 XML 文件
新的 XML 文件
新的 XML 文件

最后,这些天气预报就更容易阅读了。

图 52. 格式化的消息
格式化的消息
格式化的消息

如果您觉得这个方法不适合您,您可以使用您自己的方法格式化这个 HTML 输出。大多数 Web 服务都支持 XML 输出,所以您不需要总是使用这个方法处理格式化。

结束语

我们已经使用 Web Services Validation Tool for WSDL and SOAP 创建、发送、接收并验证了 SOAP 消息。Web Services Validation Tool for WSDL and SOAP 能够查明那些大多数 Web 服务服务器无法发现的问题,这些问题在实际中可能导致灾难性后果。如果在开发阶段使用这个工具,我们可以缩短解决生产环境中遇到的问题的处理时间。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=SOA and web services
ArticleID=626732
ArticleTitle=Web 服务 SOAP 消息验证
publish-date=02142011