1.0 简介
本文档对 Project Tango 进行全面概述。Project Tango 是由 Sun Microsystems 开发的一个针对关键企业 Web 服务规范(通常称为 WS-*)的开源实现,它提供了与 .NET 3.0 的互操作性。
本文档不是一篇 Web 服务教程,您需要对 Web 服务的基本知识具有一定的了解。参考资料部分提供的资源可帮助您了解如何构建 Web 服务。
2.0 什么是 Project Metro?
Project Tango 是 Project Metro(也称为 Metro)的一个关键组件,而 Project Metro 是 GlassFish V2 中的 Web 服务栈。要更好地理解 Project Tango,最好对 Metro 比较熟悉。
Project Metro 是来自 Sun Microsystems 的 Web 服务栈。此服务栈集成在 GlassFish V2 中,后者是一个高性能、具有产品级质量而且与 Java Platform, Enterprise Edition (Java EE) 5 技术兼容的应用服务器。图 1 显示了 Metro 的所有组件。

图 1:Metro – GlassFish Web 服务栈
Metro 的主要组件可以分为两类:
Java API for XML Web Services (JAX-WS) RI 提供了核心 Web 服务平台。其中包括所有的 SOAP 消息功能,比如 WS-Addressing 和 MTOM。JAX-WS RI 是 JAX-WS 规范的一个实现,是作为 JSR 224 在 Java Community Process (JCP) 中开发的。
Project Tango 使用由一些 WS-* 规范定义的协议和机制在 Core 层实现对 Security、Reliability 和 Transactions 的支持。这使得 Java 客户机可以使用这些协议与 Java 端点通信。另外,这些协议也支持与 .NET 3.0 框架的 Windows Communication Foundation 组件进行互操作。
JAX-WS 具有一个可扩展的架构和一个 Commons 区域,用来收集对 JAX-WS RI 有用的插件和扩展。例如,SMTP Transport 支持用于使用电子邮件和 JSON 发送和接收消息,而不使用 SOAP 或 Plain Old XML (POX) 对消息进行编解码。还使用了一些 XML 处理 API,比如 JAXB for XML<->Java Data Binding 和用于格式化和访问客户机和服务器中的 XML 消息的 JAXP。
Metro 上的所有应用程序都能够使用 NetBeans 5.5.1 架构轻松开发,并部署到 GlassFish V2 上。
本文档将详细介绍 Project Tango。

有句英语俗语叫做“两个人才能跳探戈”。Project Tango 通过与 .NET 3.0 框架的交互性提供了关键 WS-* 技术的一个实现。因此这个名字的寓意就是两个 Web 服务栈之间的探戈,或舞蹈。其徽标显示了一个公爵嘴里叼着玫瑰在探戈舞台上摆的一个造型。
3.0 什么是 Project Tango?
Project Tango(也称为 WSIT for Web Services Interoperability Technology)是 GlassFish V2 的一个集成部分,它是一些关键企业 Web 服务技术的一个开源实现,这些技术通常称为 WS-*。这些技术分为三个主要区域:安全性(Security)、可靠性(Reliability)和事务(Transactions)。
Project Tango 的一个主要用途是提供与 Windows Communication Foundation 的互操作性,后者是绑定到 .NET 3.0 平台的 Web 服务栈。
图 2 显示了图 1 的更详细的视图。其中显示了 Security、Reliability 和 Transactions 区域中由 Project Tango 实现的不同 WS-* 规范。该图还显示了 Metadata,这是一个新的 Project Tango 组件,将在下面介绍。
在 Security 区域中,WS-Security 1.0 和 1.1 提供了 Web 服务中 SOAP 消息层安全性的一个基本框架。WS-Trust 定义发出、更新和验证安全令牌的框架,并在不同信任域中建立信任关系。WS-Secure Conversation 通过为多个消息交换定义安全消息交换语义来提升整体性能和安全性。WS-Security Policy 允许 Web 服务端点以交互的方式向潜在客户机指定它们的安全需求。

图 2:Project Tango – 关键组件
Project Tango 实现的规范版本如下:
- OASIS WS-Security 1.0 和 1.1
- WS-Trust(2005 年 2 月)
- WS-Secure Conversation(2005 年 2 月)
- WS-Security Policy(2005 年 7 月)
- WS-Reliable Messaging(2005 年 2 月)
- WS-Reliable Messaging Policy(2005 年 2 月)
- WS-Coordination(2005 年 8 月)
- WS-Atomic Transactions(2004 年 10 月)
- WS-Metadata Exchange(2004 年 10 月)
- WS-Policy(W3C 成员提交)
- WS-Policy Attachment(W3C 成员提交)
.NET 3.0 也实现了相同的版本。
http://wsit.dev.java.net/specification-links.html 上列出了这些规范的详细信息。Tango 的下一个版本中的规范版本将与 .NET 3.5 一致。
在 Reliability 区域中,WS-Reliable Messaging 定义一个消息传递协议,用于识别、跟踪和管理两方(一个源和一个目的地)之间的可靠消息传递。WS-Reliable Messaging Policy 使得 Web 服务端点可以指示需要一个可靠的消息传递。
在 Transactions 区域中,WS-Coordination 提供了一个可扩展的框架,用于定义一些协议的协调上下文和类型,从而协调分布式动作。WS-Atomic Transactions 提供了事务上下文和原子事务协调类型的定义,该定义将用于由 WS-Coordination 定义的框架中。这允许事务在 Web 服务上流动。
上面的 WS-* 规范定义的消息格式和机制支持在线互操作性。但是,WSDL 互操作性对于客户机理解端点需求和端点理解客户机需求具有同等的重要性。图 2 中新增的 Metadata 标签框能够实现此目的。这个框标识了一些机制,这些机制允许端点发布 Security、Reliability 和 Transactional 功能,也允许客户机以互操作的方式使用这些功能。WS-Policy 定义一个用于表示端点功能的一般目标框架。这个可扩展的框架然后用于定义特定于域的策略声明。客户机使用 WS-Metadata Exchange 和 WS-Transfer 检索关于此端点的信息。
Project Tango 提供了所有上述功能,这些功能被构建为 JAX-WS RI 的一个扩展。
3.1 Tango 的价值主张是什么?
Project Tango 的两个主要的价值主张如下:
-
关键 WS-* 规范的一个实现
-
与 .NET 3.0 框架的互操作性

图 3:Project Metro – 价值主张
Tango 提供关键企业 Web 服务技术(通常称为 WS-*)的一个实现,该实现提供了与 Windows Communication Foundation 的互操作性,后者是 .NET 3.0 框架的一个组件,提供了 Microsoft 的用于构建分布式应用程序的统一框架。
图 3 显示了 Metro(Tango 是其关键组件)如何为同类和不同类的体系结构提供完整 Web 服务解决方案。
对于任何 Web 服务通信,都有一个调用 Endpoint 的 Client。Endpoint 将其功能作为元数据 发布,Client 使用这些元数据引导与 Endpoint 之间的通信。此元数据指示哪些功能 — Security、Reliability 和 Transactions — 受 Endpoint 支持。图中显示了一对 Client 和 Endpoint,其中一个使用 Metro,另一个使用 .NET 3.0。可以在 GlassFish V2 支持的任何平台上部署 Metro Client 和 Endpoint。可以在 .NET 3.0 支持的任何平台上部署 .NET 3.0 Client 和 Endpoint。
什么是互操作性 plug-fest?
互操作性 Plug-fest 是一个专注于 WS-* 规范的 Web 服务互操作性活动,该活动由 Microsoft 主持,多家供应商参与。在每个 plug-fest 活动中,参与者携带他们的 Web 服务栈,并对使用这些规范定义的场景和测试用例进行互操作。关于即将实施的活动和场景的详细信息,请参阅
http://www.mssoapinterop.org/ilab/。Sun 在 plugfest 活动的参与者信息可以在
http://blogs.sun.com/arungupta/tags/plugfest 上找到。
对于同一种类的体系结构(其中 Client 和 Endpoint 都使用 Metro),标号为 1 的箭头显示了一个 Metro Client 正在调用一个 Metro Endpoint。如果这符合您的意图,那么您只需一个作为 Metro 运行时的 GlassFish V2、作为工具的 NetBeans IDE,以及提供了开发、部署和调用此端点的详细步骤的 WSIT 教程。
对于不同种类的体系结构(其中只有一个 Client 或 Endpoint 使用 Metro,另一个基于 .NET 3.0),标号为 2 和 3 的箭头显示一个 Metro 客户机可以调用一个 .NET 3.0 端点,而一个 .NET 3.0 客户机也可以调用一个 Metro 端点。同时,NetBeans IDE 允许使用 Tango 功能的任何组合发布一个 Web 服务端点,以及调用 .NET 3.0 运行时上的 Web 服务端点。
Sun 与 Microsoft 一起参加了多个互操作性 plug-fest 活动,以确保双方的 Web 服务栈的实现能够是完全可互操作的。
4.0 Tango 编程模型
Project Tango 的美妙之处在于,它没有引入新的编程模型。它利用现有的 JAX-WS 和 EJB 编程模型,而且允许以将一个附加配置文件绑定到应用程序的方式定义端点上的 Security、Reliability 和 Transactional 功能。图 4 的中间部分显示了 WSIT 配置文件。

图 4:Tango 服务器编程模型
使用带 WSIT 插件的 NetBeans 5.5.1 IDE 可以轻易地生成配置文件。可以从 NetBeans Update Center 安装 WSIT 插件。另一种方法是手动创建配置文件,但这需要掌握不同的特定于域的策略语言的知识。因此,使用 NetBeans IDE 生成配置文件是首选的方法。可以在其他 IDE 中生成 WSIT 配置文件,只要在这些 IDE 中可以使用 WSIT 插件。附录 A 提供了一个启用 Security、Reliability 和 Transactions 的配置文件示例。
配置文件会根据 JSR-109 或 Servlet 部署模型而被放在合适的目录中。如果 NetBeans IDE 被用于打包或部署应用程序,那么这一步就会是透明的。
在客户端,可以使用一个可选的 WSIT 配置文件来制定某些客户端参数,比如 Reliable Messaging 超时或信任和关键存储的位置。此文件位于类路径的 META-INF 目录。WSIT 教程中包含了 WSIT 配置文件的完整细节。
GlassFish V2 是一个高性能、具有产品级质量,而且与 Java EE5 兼容的应用服务器,它为支持 WSIT 的端点提供了推荐的部署平台。可从
http://glassfish.java.net 下载 GlassFish
5.0 容器和工具
使用任何 Project Tango 特性开发的 Web 服务端点都可以部署到以下平台:
-
GlassFish V2 – 其中集成了 Project Tango,而且是推荐的平台。
-
Apache Tomcat – Project Tango 的单机版本(可从 wsit.dev.java.net 上获得),提供了一个用于在 Apache Tomcat 上安装实现的安装脚本。
-
Jetty – 其试验性支持记录在 http://blogs.sun.com/arungupta/entry/tango_on_jetty 上。
-

NetBeans IDE 5.5.1 和 WSIT 插件提供了开发、配置和部署启用 WSIT 的端点的工具时间支持。可从此链接下载 IDE:
http://netbeans.org
Java SE 中的端点 API – 其试验性支持记录在 http://blogs.sun.com/theaquarium/entry/glassfish_web_services_stack_tango 上。
可以将 Metro 安装在任何符合 Servlet 2.4 的 Web 上。
NetBeans IDE 能够非常出色地支持从 Java 启功的支持 WSIT 的 Web 服务端点的开发、配置和部署。该 IDE 还提供了一些机制,可用于调用使用 WSDL 描述的 Web 服务端点。
IDE 需要从 NetBeans Update Center 更新以安装 WSIT 插件,以在 Web 服务端点上配置 WSIT 功能。创建一个 Web 服务之后,此 Web 服务将带有一个名为 Edit Web Service Attributes 的文本菜单。图 5 显示当选中此菜单项时弹出的窗口截图。

图 5:NetBeans IDE 中的 WSIT 配置
要启用 Reliable Messaging,只需选中 Reliable Message Delivery 复选框。单击 OK 之后会生成 WSIT 配置文件。然后配置文件会像 4.0 小节中描述的那样被打包。然后使用配置文件生成带有正确的策略声明的 WSDL。
类似地,也可以在一个端点上或者根据每个操作启用 Security。图 6 显示了 Project Tango 中定义的不同的安全性配置,可以应用到客户机和端点上。端点的每个方法也可以启用 Transactions 支持。在每一种情况,都会在配置文件中生成并捕获合适的特定于域的策略声明。

图 6:WSIT 插件中的安全性配置
关于配置每个 Tango 特性(Reliability、Security、Transactions)的更多细节将在本文档稍后各自的章节中介绍。根据项目中选择的 WSIT 特性生成并打包 WSIT 配置文件。容器中的 Metro 运行时生成带有合适的策略声明的 WSDL。NetBeans IDE 还提供了一个文本菜单,用于在选择的容器中部署项目。
NetBeans IDE 允许从 WSDL 使用 WSIT 插件支持的特性生成客户端工件。一个新的 Web Service References 节点会被添加到 NetBeans 项目,如 图 7 所示。

图 7:NetBeans IDE 中的客户端工件
此节点包含针对每个由 Web 服务公开的操作的子节点。可以将子节点拖放到任何 Java 代码中(例如 JSP 或 Java 类),从而生成样板化代码调用 Web 服务。
简而言之,NetBeans IDE 和 GlassFish V2 提供了对开发、部署和调用使用任何 WSIT 功能 Web 服务端点的优秀支持。
6.0 安全性
Tango 中的 Security 支持是 OASIS WS-Security 1.0 和 1.1、WS-Trust(2005 年 2 月 )、WS-Secure Conversation(2005 年 2 月 )和 WS-Security Policy(2005 年 7 月)规范的一个实现。该实现提供了一个框架,可以以互操作的方式保护客户机和端点之间的 SOAP 消息交换。
OASIS Web 服务技术委员会(Technical Committee,TC)发布了 WS-Security (WSS) 1.0 和 1.1 规范。这些规范构建在现有安全性技术(比如 XML Digital Signature、XML Encryption 和 X.509 Certificates)之上,它们提供了一个针对 Web 服务中的 SOAP 消息级安全性的行业标准框架。WSS 支持多种安全令牌格式(比如 Username Token),它描述了 Web 服务端点如何提供一个 UsernameToken 作为根据“用户名”标识请求者的一种方式,也可以使用“密码”来验证客户机的身份。NetBeans IDE 定义一些安全性配置,以配置 Web服务客户机和端点的安全性。这些配置允许开发人员选择消息的完整性和机密性,也可以通过选择 IDE 中的一个选项来选择令牌格式。
WS-Trust 定义发出、更新和验证安全令牌的框架,并在不同信任域中建立信任关系。此规范解决了信任互操作性 的问题。这意味着即使一个 Web 服务端点能够接受给定的安全令牌格式,语法级别的互操作性也不能保证使用者将会信任此令牌。例如,尽管一个 Web 服务端点支持来自客户机的 X.509 令牌,但这并不意味着它将会接受来自任何认证授权(Certificate Authority,CA)的 X.509 令牌。端点需要拥有对 CA 的必要的信任,以验证 X.509 证书。WS-Trust 通过定义一个大体的令牌发布框架解决了这个问题,该框架由一个 Security Token Service (STS) 使用。

图 8:Security Token Service (STS) 消息流
图 8 显示了当 STS 发布的令牌被用于保护消息交换时 Client、Endpoint 和 STS 之间的消息流。Client 和 Endpoint 要进行通信,客户机需向 Endpoint 请求元数据(标号为 1 的箭头)。虚线箭头指示客户机上的 WSIT 运行时(完全对应用程序透明)启动请求。如果收到的元数据(标号为 2 的箭头)指示需要一个来自特定 STS 的安全令牌,则 Client 发布另一个请求(标号为 3 的箭头)以获得 STS 的元数据。来自 STS 的响应消息(标号为 4 的箭头)指示将用于与它通信的安全令牌的类型。满足了从 STS 元数据获得的安全性需求之后,Client 从 STS 请求一个安全令牌(标号为 5 的箭头),并收到一个包含所发布的令牌的响应(标号为 6 的箭头)。Client 然后调用带有发布的令牌的 Endpoint(标号为 7 的箭头)。Endpoint 然后验证来自 Client 的请求,并处理请求,向 Client 返回响应(标号为 8 的箭头)。标号为 1 到 6 的箭头是协议消息,这些消息有 WSIT 运行时代表 Client 发出,用来收集将在应用层消息中使用的元数据(标号为 7 和 8 的消息)。
一个应用程序可以跨越多个安全域,其中每个域都有自己的 STS。多个 STS 可以彼此链接起来,以组织多个安全域之间的信任。此模式称为一个 brokered trust,并受 Project Tango 支持。附录 B 描述了一个使用 brokered trust 的真实场景。
WS-Secure Conversation 通过定义多个消息交换的安全消息交换来提升消息的整体性能和安全性。该规范定义用于建立和共享安全性上下文,以及从建立的安全性上下文提取密钥的机制。在一个通信会话的生存期中的多个通信方共享安全性上下文。一旦建立了上下文,提取的密钥就会被用于安全性上下文中每个密钥的用途。规范定义了创建安全性上下文的 3 中方法:

图 9:“STS Issued Token”的安全性配置
使用 NetBeans IDE,可以在一个端点上或者根据每个操作启用 Security。NetBeans IDE 定义一些安全性配置,以配置 Web服务客户机和端点的安全性。图 6 显示了可以从 IDE 中配置的安全性配置示例。例如,如果选择了“STS Issued Token”配置,则每个操作上的安全令牌都可以如 图 9 中那样配置。
Tango 支持细粒度的安全性配置,如 图 10 所示。使用 NetBeans IDE,SOAP 消息或带 XPath 标识的元素的标准头部都可以被签名和加密。

图 10:细粒度安全性配置
选择了安全性机制之后,将会在 WSIT 配置文件中生成合适的 WS-Security Policy 声明。然后使用配置文件生成带有正确的策略声明的 WSDL。
7.0 可靠性
Tango 中的 Reliability 支持是 WS-Reliable Messaging(2005 年 2 月)和 WS-Reliable Messaging Policy Assertion(2005 年 2 月)规范的一个实现。
WS-Reliable Messaging 定义一个带有 SOAP 绑定的基于线路的消息传递协议,,用于标识、跟踪和管理两方之间的消息传递,一个 Source(例如 Client)和一个 Destination(例如 Endpoint)。简单来说,Source 定期询问 Destination,以了解哪条消息已到达,然后根据此信息重新发送消息(如果需要)。这允许 Destination 按照消息发送的顺序为来自 Source 的消息重新创建一个精确的消息流。WS-Reliable Messaging 引入了 Reliable Messaging Source (RMS) 和 Reliable Messaging Destination (RMD),分别用于封装 Source 和 Destination 上的消息流的发送、重发送和重创建功能。
RMD 和 Destination 可以重新创建消息流的范围在 Reliable Messaging 术语中称为 Delivery Assurance。RMD 提供了 3 种级别的 Delivery Assurance:
-
AtMostOnce – 至多只能传送一次且没有副本的消息,否则将会出现一个错误。序列中的一些消息可能不会被传递。
-
AtLeastOnce – 每条消息都将被传送,否则将出现一个错误。一些消息可能被传送多次。
-
InOrder – 所有消息都会按发送的顺序进行传递。这个级别需要最终接收者观察到的序列没有减少。这意味着既不能重复也不能遗漏。
图 11 显示了一个没有任何 Reliable Messaging 支持的消息传递系统。Source 和 Destination 通过没有 Reliable Messaging 支持的 Web 服务运行时通信。箭头中的“x”指示应用程序消息可能丢失或某个传递方向出错。在这种情况下,无需来自计算机和 Web 服务运行时的任何 Reliable Messaging 支持,Source 和 Destination 会负责消息的恢复。

图 11:没有 Reliable Messaging 支持的消息传递系统
图 12 显示带有 Reliable Messaging 支持的消息传递系统。在这种情况下,Source 和 Destination 之间的消息通过嵌入到 Web 服务运行时中的 RMS 和 RMD 交换。现在使用 Reliable Messaging 协议,RMS 和 RMD 可以以一种可靠的方式进行通信,它们分别代表 Source 和 Destination,并且实现 delivery assurance。注意,不管那一端的应用程序代码和 Reliable Messaging 组件之间都不能直接通信。根据 WSDL 中的 Reliable Messaging Policy 声明,RMS 和 RMD 都会自动启用。

图 12:带有 Reliable Messaging 支持的消息传递系统
可以使用 NetBeans IDE 通过选择 Reliable Message Delivery 轻易地启用 Web 服务端点上的 Reliable Messaging 支持,如 图 13 所示。WSIT 教程提供了更多细节。

图 13:WSIT 插件中的 Reliable Messaging 支持
8.0 事务
Tango 中的 Transaction 支持是 WS-Coordination(2004 年 10 月)和 WS-Atomic Transactions(2004 年 10 月)规范的一个实现。
Tango 中的 Transactions 支持使 Java EE 事务(由 JTA 定义)能够使用支持 WS-Atomic Transactions (WS-AT) 和 WS-Coordination 的 Web 服务跨不同种类系统运行。该支持提供了一致的故障和恢复语义,因此应用程序不再需要确定多方之间相互一致的决定,或者思考如何从大量可能的不一致状态中恢复。
本节解释 WS-Coordination 和 WS-Atomic Transactions 规范如何提供一个框架,以在 Web 服务之上启用 JTA 事务。但是,开发人员只需启用 Transactions 支持,在本节末尾将会说明。
WS-Coordination 规范定义一个扩展的框架,该框架通过一个 Coordinator 和一个协调协议集来协调活动。每个 Coordinator 可以支持多个协调协议。该规范还定义了协调上下文 的结构和在协调服务之间的协调上下文需求。协调上下文附带了应用程序消息,而且包含其他应用程序需要的信息。
WS-Atomic Transaction 规范提供了原子事务协调类型的定义,该类型将用于 WS-Coordination 规范中定义的可扩展框架。该类型用于协调具有“all or nothing”属性的活动,一般称为 Atomic、Consistent、Isolated、Durable (ACID)。它还定义一个原子事务上下文 来保存所有应用程序消息上的事务语义。
Project Tango 支持 WS-Atomic Transaction 规范中定义的 Durable two-phase Commit (Durable 2PC) 协议。参与者使用该协议管理持久资源,如一个数据库。Web 服务中所有的 XAResources 都被映射到一个持久 2PC 资源。
当在 JTA 事务范围内第一次调用事务性 Web 服务操作时,Project Tango 就会创建一个 Atomic Transaction Context。例如,在 代码示例 1 中,WS-AT 在第 05 行创建:
-
|
01 @Resource
02 javax.transaction.UserTransaction ut;
03
04 ut.begin();
05 bankWebService.makeWithdrawl();
06 ...
07 ut.commit();
|
代码示例 1:WS-AT 事务上下文创建
当未使用该功能时,不会增加 JavaEE 事务上的开销。此上下文与应用程序消息一起传递。来自包含事务上下文的 .NET 3.0 客户机的请求也由 Project Tango 理解,并加入到事务上下文中。
Tango 中的 Transactions 特性支持以下内容:
-
从 Web 层和 EJB 层传递过来的 WS-AT Transactions
-
从 Container Managed Transactions 到语义上相等的 WS-Atomic Transaction 策略声明的自动映射。
-
XAResources 的自动获得 – GlassFish V2 中的 JMS 实现、使用 JavaDB 的 TopLink Essentials Entity 管理器、Hibernate 的 Entity 管理器
WS-AT 规范也定义用于描述端点的事务性功能的策略声明。可以使用 NetBeans IDE 基于每个操作轻易地启用 Web 服务端点上的事务性功能。图 14 显示可用于配置一个操作上的 WS-AT 支持的不同选项。选择一个操作上的 Transaction 类型将会在 WSIT 配置文件中生成合适的 WS-AT 策略声明。该配置文件然后用于生成 WSDL。WSIT 教程拥有更多细节。

图 14:WSIT 插件中的原子事务配置
Project Tango 的事务特性只适合于 GlassFish V2 容器。
9.0 参考资料
-
wsit.dev.java.net – Project Tango
-
metro.dev.java.net – Project Metro
-
glassfish.dev.java.net – GlassFish V2 应用服务器
-
jax-ws.dev.java.net – JAX-WS
-
netbeans.org – NetBeans IDE
-
http://sessions.sun.com/learning/javaoneonline/sessions/2007/TS-4865/index.html – 带有音频和同步副本的 JavaOne 207 Technical Session。
-
java.sun.com/webservices/interop – Sun 上的 Webf Web Services Interoperability 成就的登录页面
-
planet.sun.com/webservices/group/blogs/ – 来自 Sun 的 Web 服务工程小组的博客集合
-
wsit-docs.dev.java.net/releases/m5/ – WSIT 教程
-
http://java.sun.com/javaee/5/docs/tutorial/doc/JAXWS.html#wp72279 – 如何使用 JAX-WS 构建 Web 服务
-
wsit.dev.java.net/screencasts.html – WSIT Screencasts
附录 A – WSIT 配置文件示例
此附录包含一个 Web 服务端点的代码和该端点的 WSIT 配置文件,在启用 Security (STS Issued Token Profile)、Reliability 和 Transactions 之后由 NetBeans IDE 生成。
Web 服务端点代码如下:
package server;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
*
* @author Arun Gupta
*/
@WebService()
public class HelloWebService {
/**
* Web service operation
*/
@WebMethod
public String sayHello(@WebParam(name = "name") String name) {
return "Hello " + name;
}
}
在启用 Security (STS Issued Token profile)、Reliability 和 Transactions 之后由 NetBeans IDE 生成的 WSIT 配置文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="HelloWebServiceService" targetNamespace="http://server/" xmlns:tns="http://server/" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsaws="http://www.w3.org/2005/08/addressing" xmlns:wsrm="http://schemas.xmlsoap.org/ws/2005/02/rm/policy" xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:sc="http://schemas.sun.com/2006/03/wss/server" xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy" xmlns:wsat="http://schemas.xmlsoap.org/ws/2004/10/wsat" xmlns:wsp2002="http://schemas.xmlsoap.org/ws/2002/12/policy"
>
<message name="sayHello"/>
<message name="sayHelloResponse"/>
<portType name="HelloWebService">
<wsdl:operation name="sayHello">
<wsdl:input message="tns:sayHello"/>
<wsdl:output message="tns:sayHelloResponse"/>
</wsdl:operation>
</portType>
<binding name="HelloWebServicePortBinding" type="tns:HelloWebService">
<wsp:PolicyReference URI="#HelloWebServicePortBindingPolicy"/>
<wsdl:operation name="sayHello">
<wsp:PolicyReference URI="#HelloWebServicePortBinding_sayHello_Policy"/>
<wsdl:input>
<wsp:PolicyReference URI="#HelloWebServicePortBinding_sayHello_Input_Policy"/>
</wsdl:input>
<wsdl:output>
<wsp:PolicyReference URI="#HelloWebServicePortBinding_sayHello_Output_Policy"/>
</wsdl:output>
</wsdl:operation>
</binding>
<service name="HelloWebServiceService">
<wsdl:port name="HelloWebServicePort" binding="tns:HelloWebServicePortBinding"/>
</service>
<wsp:Policy wsu:Id="HelloWebServicePortBindingPolicy">
<wsp:ExactlyOne>
<wsp:All>
<wsaws:UsingAddressing xmlns:wsaws="http://www.w3.org/2006/05/addressing/wsdl"/>
<wsrm:RMAssertion/>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:SecureConversationToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:RequireDerivedKeys/>
<sp:BootstrapPolicy>
<wsp:Policy>
<sp:SymmetricBinding>
<wsp:Policy>
<sp:ProtectionToken>
<wsp:Policy>
<sp:IssuedToken sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/AlwaysToRecipient">
<sp:RequestSecurityTokenTemplate>
<t:TokenType>http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1</t:TokenType>
<t:KeyType>http://schemas.xmlsoap.org/ws/2005/02/trust/SymmetricKey</t:KeyType>
<t:KeySize>256</t:KeySize>
</sp:RequestSecurityTokenTemplate>
<wsp:Policy>
<sp:RequireInternalReference/>
</wsp:Policy>
</sp:IssuedToken>
</wsp:Policy>
</sp:ProtectionToken>
<sp:Layout>
<wsp:Policy>
<sp:Lax/>
</wsp:Policy>
</sp:Layout>
<sp:IncludeTimestamp/>
<sp:OnlySignEntireHeadersAndBody/>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
<sp:MustSupportRefIssuerSerial/>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
</wsp:Policy>
</sp:Wss11>
<sp:Trust10>
<wsp:Policy>
<sp:MustSupportIssuedTokens/>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
</wsp:Policy>
</sp:Trust10>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body/>
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="AckRequested" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="SequenceAcknowledgement" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="Sequence" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
</sp:SignedParts>
</wsp:Policy>
</sp:BootstrapPolicy>
</wsp:Policy>
</sp:SecureConversationToken>
</wsp:Policy>
</sp:ProtectionToken>
<sp:Layout>
<wsp:Policy>
<sp:Strict/>
</wsp:Policy>
</sp:Layout>
<sp:AlgorithmSuite>
<wsp:Policy>
<sp:Basic128/>
</wsp:Policy>
</sp:AlgorithmSuite>
<sp:IncludeTimestamp/>
<sp:OnlySignEntireHeadersAndBody/>
</wsp:Policy>
</sp:SymmetricBinding>
<sp:Wss11>
<wsp:Policy>
<sp:MustSupportRefKeyIdentifier/>
<sp:MustSupportRefIssuerSerial/>
<sp:MustSupportRefThumbprint/>
<sp:MustSupportRefEncryptedKey/>
</wsp:Policy>
</sp:Wss11>
<sp:Trust10>
<wsp:Policy>
<sp:RequireClientEntropy/>
<sp:RequireServerEntropy/>
<sp:MustSupportIssuedTokens/>
</wsp:Policy>
</sp:Trust10>
<sc:KeyStore wspp:visibility="private" storepass="changeit" type="JKS" location="C:\testbed\b50\glassfish\domains\domain1\config\keystore.jks"/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="HelloWebServicePortBinding_sayHello_Input_Policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body/>
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="AckRequested" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="SequenceAcknowledgement" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="Sequence" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="HelloWebServicePortBinding_sayHello_Output_Policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:EncryptedParts>
<sp:Body/>
</sp:EncryptedParts>
<sp:SignedParts>
<sp:Body/>
<sp:Header Name="To" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="From" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="FaultTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="ReplyTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="MessageID" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="RelatesTo" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="Action" Namespace="http://www.w3.org/2005/08/addressing"/>
<sp:Header Name="AckRequested" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="SequenceAcknowledgement" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
<sp:Header Name="Sequence" Namespace="http://schemas.xmlsoap.org/ws/2005/02/rm"/>
</sp:SignedParts>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<wsp:Policy wsu:Id="HelloWebServicePortBinding_sayHello_Policy">
<wsp:ExactlyOne>
<wsp:All>
<wsat:ATAssertion wsp:Optional="true" wsp2002:Optional="true"/>
<wsat:ATAlwaysCapability/>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</definitions>
附录 B – Brokered Trust 示例
此附录将使用一个真实的场景解释 Brokered Trust 模式。
图 15 显示了一个复合 Web 服务的业务场景和消息流。它包含一个在 Metro 托管的环境中运行的 Retail Quote Service (RQS),使用运行在相同的安全域中的 Wholesale Quote Service (WQS),向运行在 Metro 和 .NET 环境的客户机提供汽车报价。
此 RQS 也从一个运行在不同安全域的使用 .NET 3.0 框架的 WQS 获得一个竞争性的出价。每个域都有自己的 Security Token Service,用于向运行在不同安全域的客户机发布令牌。
每个客户机根据自己的身份可能获得不同的折扣。为了便于身份管理,RQS 还有一个运行在 Internet 上的 STS。.NET 客户机在 Internet 上与此 STS 通信,获得令牌,并使用该 STS 验证 RQS。客户机以一种安全的方式与 RQS 通信。RQS 以一种安全可靠的方式与两个 WQS 通信。

图 15:使用 Project Tango 的 Brokered Trus 模式
消息流将在下面解释。其中的数字对应图 15 中的箭头。
|
0
|
在两个安全域(Metro 和 .NET 托管)中的 Web 服务能彼此通信之前,需通过两个 STS 之间的一种 out of band 信任建立这两个安全域之间的信任关系。
|
|
1
|
NET 客户机请求 RQS 的元数据并收到一个响应。元数据提供了外部 STS 的位置,以获得安全令牌。
|
|
2
|
NET 客户机运行时然后从指定的 STS 获得安全令牌。
|
|
3
|
NET 客户机使用安全令牌向 RQS 发起一个业务请求。
|
|
4
|
RQS 收到来自 .NET 托管环境中的 WQS 的元数据。收到的元数据提供 .NET 托管环境中 STS 的位置。
|
|
5
|
RQS 运行时向指定的 STS 请求元数据。元数据提供 Metro 托管环境中 STS 的位置。
|
|
6
|
在相同的安全域,此 STS 向 RQS 提供令牌。
|
|
7
|
RQS 运行时使用此令牌从运行在 .NET 托管环境中的 STS 获得新令牌。
|
|
8
|
使用这些令牌,RQS 使用合适的凭证向 WQS 发送一个请求。
|
|
9
|
WQS 验证该凭证,处理请求,然后返回响应。
|
|
10
|
RQS 收到来自 Metro 托管环境中的 WQS 的元数据。
|
|
11
|
RQS 向 WQS 发送一个请求。
|
|
12
|
WQS 验证该凭证,处理请求,然后返回响应。
|
|
13
|
在将来自两个 WQS 的响应集合起来之后,一个请求将返回到客户机。
|
可以将此模式进一步扩展,以将多个 STS 链接起来。
在上述操作中,由开发人员显式地发起的惟一操作就是通过由服务提供的 WSDL 生成客户机代理(箭头 1),以及调用业务方法(箭头 3)。所有的其他交互则由 Tango 基础架构处理。
|