级别: 中级 Antonio Gallo (agallo73@yahoo.it), IT 专家, Banca d'Italia Maria Gallo (maria.gallo@it.ibm.com), 软件开发人员, IBM Michele Crudele (michele.crudele@it.ibm.com), 软件架构师, IBM
2008 年 5 月 14 日
本系列旨在通过真实的案例场景帮助理解 SOA 概念。我们在前两篇文章中讨论了 XML 加密、IBM® WebSphere® DataPower® Appliances 的优势以及使用 IBM WebSphere Enterprise Service Bus 进行协议切换和中介的好处。接下来我们将重点关注 WebSphere Enterprise Service Bus 的模式验证功能。本文将帮助您深入了解中介模块,并要介绍相应的配置步骤,以便让 WebSphere Enterprise Service Bus 识别加密数据和对包含保密信息的消息执行协议切换和中介。
引言
本文假定您已经读过了本系列的前面两个部分的内容,而且熟悉此场景中的卫生保健预约系统及其体系结构框架。
在此场景中,远程诊所将客户就诊功能完全委托给中央系统,中央系统会为每个服务提供者(诊所)准备数据、通过 WebSphere DataPower XML Security Gateway XS40 计算单元加密保密信息,然后将其发送到 WebSphere Enterprise Service Bus。完整的体系结构图如下面的图 1 中所示。
图 1. 预约系统
此部分提供关于配置 WebSphere Enterprise Service Bus 进行以下任务的详细信息:
-
识别加密数据:WebSphere Enterprise Service Bus 具有严格的模式验证功能,应用于通过导出绑定传入的数据。如果传入消息的格式与导出接口的定义不匹配,会将此消息从 WebSphere Enterprise Service Bus 丢弃,并引发异常。您必须告知 WebSphere Enterprise Service Bus 加密数据的结构,并同时提供临时数据类型和接口。
-
执行协议切换:WebSphere Enterprise Service Bus 将这些消息作为 SOAP/HTTP 请求获取,然后使用特定的导入和导出绑定将其转发到 Java™ Message Service (JMS) 主题。导出绑定 描述客户机如何与中介模块通信。而导入绑定 则描述中介模块如何与所定义的服务通信。绑定可保证透明传输协议切换功能,并允许中央预约系统在无需在应用程序代码中添加任何通信逻辑的情况下连接到各个诊所。
图 2. 协议切换
-
使用消息选择器:根据 JMS 规范,JMS 客户机可以使用消息选择器进行筛选,从而确定自己应该处理哪些消息。因为每个诊所都仅希望接收到以自身为目的地的数据,因此 JMS 消息的 Header 中应该包括
serviceProviderId。从 V6.0.2 开始,WebSphere Enterprise Service Bus 就提供可以用于此用途的 message element setter 中介原语:中介模块获得请求消息时,会检查传入消息格式,利用 message setter 原语从 SOAP 主体检索服务提供者 ID,将其存储在(通过复制操作)输出消息的 JMS Header 中(请参见图 3)。
图 3. 消息选择器
为了实现所描述的场景,我们定义了中介模块,并将其连接到 SOAP/HTTP 导出绑定和 JMS 导入绑定。
中介模块
中介模块由四个功能块组成:
-
导出接口,用于获得包含敏感数据的 SOAP HTTP 消息
-
消息选择器,用于使用选择器信息充实 JMS 消息 Header
-
XSLT 转换,负责将导出接口和导入接口匹配,从而说明可以如何提供中介逻辑(甚至在消息包含加密数据的情况下)
-
导入接口,将敏感数据作为 JMS 有效负载发送到主题
图 4 显示了中介模块。
图 4. 中介模块
本文将说明如何构建组成中介模块的所有功能部件。在下面的各个部分中,您可以找到完成以下任务所需的步骤的详细信息:
- 创建新库。
- 定义数据类型。
- 定义导出和导入接口。
- 定义中介模块。
创建新库
首先,您应该创建一个新库,用于存储在中介模块中使用的数据类型和导入导出接口。可通过以下步骤完成此工作:
- 选择 File > New > Project。这将显示一个新窗口。
- 选择 Library(请参见图 5)。
图 5. 新建项目
- 在打开的窗口中,在 Library Name 字段键入
Asynch-Library,并将 Use Default 复选框保持选中状态。
- 单击 Finish。向导将立即生成库(请参见图 6)。
图 6. 新建库
定义数据类型
如果仔细阅读了本系列前面的文章,特别是第 2 部分,您就应该知道从中央预约系统传出的 SOAP 消息的格式,其中包含关于保留时段日历的所有信息,如清单 1 中所示。
清单 1. SOAP 消息
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenc="http://schemas.XMLsoap.org/soap/encoding/"
xmlns:soapenv="http://schemas.XMLsoap.org/soap/envelope/">
<soapenv:Header/>
-<soapenv:Body>
-<p374:sendUpdatedAgenda xmlns:p734="http://Asynch_Library/AsynchResSystemExport">
<xenc:EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmls:xenc="http://www.w3.org/2001/04/xmlenc#"/>
<xenc:EncryptionMetod Algorithm=""http://www.w3.org/2001/04/xmlenc#triplesdes-cbc"/>
-<dsig:KeyInfo xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey Recipient="name:ASL1_cert">
<xenc:EncryptedMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5"
-<xenc:ChiperData>
<xenc:ChiperValue >AIWDQKgc09cBkwjXNPQ8NleT5ZMvuLqQJZUijEXsvvBzhclT
czzDbFGTh67n9NMlpoiu)0p)xcfDATfgJuWQ+KKLN7DsErt543lkvuHTP+lllCV=OPPmhjkoik
jRT4589JCdxzT432LLp098B00 </xenc:ChiperValue>
</xenc:ChiperData>
</xenc:EncryptedKey >
</dsig:KeyInfo >
</xenc:ChiperData>
</xenc:EncryptedData>
<serviceProviderId >ASL1<serviceProviderId >
</p374:sendUpdatedAgenda >
</soapenv:Body>
</soapenv:Envelope>
|
如清单 1 中所示,敏感信息包含在 EncryptedData 部分中。由于 WebSphere Enterprise Service Bus 会对通过其导出绑定传入的消息进行模式验证,因此明显有必要让 WebSphere Enterprise Service Bus 能识别 EncryptedData 定义。
如果您仔细观察消息的格式,就会发现 EncryptedData 是在 W3C 标准 XML 加密命名空间中定义的元素。另外,您还会发现,就 KeyInfo 而言,其定义属于 XML 数字签名命名空间的一部分。由于这个原因,如果您从 W3C 官方站点(有关 URL,请参见参考资料部分)导入 xenc-schema(包括 XML 加密命名空间的定义)和 xmldixencg-core 模式(其中包含 XML 数字签名命名空间的定义),则完全可以让 WebSphere Enterprise Service Bus 识别 EncryptedData 类型定义。
要导入这些模式,请执行以下步骤:
- 在 IBM WebSphere Integration Developer 控制台中,选择 File > New > Other。在打开的窗口中,选中 Show All Wizards 框,然后展开 XML 文件夹,并选择 XML Schema,如图 7 中所示。
图 7. 新建 XML 模式
- 如果打开一个窗口,询问是否启用 XML 开发功能,则单击 OK,以启用所需的功能(请参见图 8)。
图 8. 确认启用
- 在 File name 字段中键入
xmldsig-core-schema.xsd,选择之前创建的库作为模式位置,然后单击 Finish,如图 9 中所示。
Figure 9. 创建 XML 模式
- 在打开的模式编辑器中,删除文件的全部内容。然后从本文的下载部分下载 xenc 模式。复制此模式的内容,并将其粘贴到模式编辑器中。最后,保存文件。
- 您应该得到一条错误消息,指示在新创建的模式中存在重复的属性 PGPKeypacket。之所以出现这个问题,是因为对于 6.0.2 FP 1 版,WebSphere Enterprise Service Bus 并不支持 choice 元素,因此会在相同模式定义中发现两个 PGPKeypacket(尽管 choice 将这两个元素标记为彼此相对的两个不同的路径),如图 10 中所示。
图 10. 中介模块
从新的 6.1 版之后,此错误已经得到解决。为了解决此问题,请取消 choice 中的两个 sequence 元素之一。我们决定删除第二个。显然,删除两个 sequence 之一时,choice 构造就没有用了,因此也必须将其从模式中删除。如果您保存此模式,之前的错误应该不会再出现了。
- 遵循上述步骤创建一个新的 XSD 文件,将其命名为 xenc-schema.xsd(请参见图 11)。
图 11. XSD 核心模式
在打开的 XSD 模式编辑器中,取消文件的全部内容。然后从本文的下载部分下载 xenc-schema.xsd 模式。复制此模式的内容,并将其粘贴到 XSD 模式编辑器中。保存文件,这次您不应该看到任何错误信息。
- 保存文件时,向导将自动对模式进行解析,并为模式中定义的每个元素类型生成新的数据类型。您可以通过展开 Asynch-Library 下的 Data Types 对此进行方便地验证(请参见图 12)。
图 12. 数据类型
具体来说,向导将生成 EncryptedDataType 数据类型,就 WebSphere Enterprise Service Bus 的模式验证而言,此类型似乎是与 EncryptedData 部分中包含的敏感数据匹配的自然对等项。既然这样,只要通过创建新的导出接口并使用 EncryptedDataType 类型的 EncryptedData 对象,就可以通过 WebSphere Enterprise Service Bus 传递加密数据。(这并非完全正确,因为需要进行轻微调整,具体请参见下面部分中所述;不过您的总体方向是正确的。)
定义导出/导入接口
现在您已经准备好定义接口了。您需要为 sendUpdatedAgenda 定义导出接口,为 publishAgenda 异步交互定义导入接口。
- 右键单击 Asynch-Library 项目,并选择 New > Interface。将其命名为
AsynchResSystemExport 并单击 Finish 按钮(请参见图 13)。
图 13. 新建导出接口
- 在出现的窗口中,选择 Add One Way Operation 图标,以添加新操作(我们曾提到需要异步交互的用例)。将新操作命名为
sendUpdatedAgenda,并添加以下两个参数(使用 Add Input 图标):
-
EncryptedDataType 类型的 EncryptedData
-
String 类型的 serviceProviderId
图 14. 导出接口
单击 Save 并关闭接口对话框。
- 即使此接口定义乍看之下似乎与 SOAP 消息的格式完美匹配,实际上并非真的如此。如果您通过右键单击接口定义并选择 open with the XML editor 选项将其打开,将会看到在 Asynch-Library 命名空间中由向导生成的
EncryptedData 元素与 xmlenc 命名空间中的 EncryptedData 元素并不匹配。为了解决此问题,请将图 15 中标红的元素注释掉,并使用绿色的元素进行替换(绿色元素是对 xmlenc 命名空间的 EncryptedData 元素的真实引用)。
图 15. 异步资源系统导出
- 完成了上面的步骤后,请选择 New Import Interface,以便为导入绑定添加新接口,如图 16 中所示。
- 右键单击 Asynch-Library 内的 Interface 文件夹,并选择 New > Interface。
- 从 Module 列表中选择 Asynch-Library,并在 Name 字段中键入
AsynchResSystemImport。
图 16. 新建导入接口
- 在打开的接口对话框中,选择 Add One Way Operation 图标,以添加新操作。将操作命名为
publishAgenda,并添加 EncryptedDataType 类型的新 EncryptedData 参数(请参见图 17)。
图 17. Publish agenda
- 重复步骤 5,以更改导入接口中的
EncryptedData 元素定义。
图 18. 异步资源系统导入
- 保存 WSDL 文件并关闭。
上述的修改并不是唯一方法,其他方法也能让加密数据正确通过 WebSphere Enterprise Service Bus 并将此数据作为 JMS 文本有效负载正确复制。如果观察一下 SOAP 消息格式,您会发现,只要对密钥和密钥的加密形式使用加密算法,KeyInfo 元素中就会包含 EncryptedKey 元素,所有信息嵌入在后者中。对于在 xmldsig 命名空间中定义的 KeyInfo,您会在模式内的 KeyInfo 元素的复制类型定义内发现列出了 EncryptedKey 元素。不过,如果通过 XML 编辑器打开 xmldsig-core-schema.xsd 文件,并查找 KeyInfo 定义,则应该看到与图 19 所示类似的情况。
图 19. xmldsig-core-schema
正如您看到的,其中没有提到 EncryptedKey 元素,但是模式假定可以添加任意元素来完成 KeyInfo 定义。因为这样,使用此模式可让 WebSphere Enterprise Service Bus 忽略传入 SOAP 消息中的任何 EncryptedKey 信息。因此,如果没有进行更改,将缺少此信息,不会复制到 JMS 有效负载中(您在处理 XSLT 转换的部分将更好地了解这样做的意思)。为了克服这个局限,您应该在 xmldsig-core-schema.xsd 模式中进行一处小更改。
- 您应该将图 20 中所示的蓝色行注释掉,并添加红色行。
图 20. xmldsig-core-schema
- 而且,由于您从其他命名空间添加元素,因此必须以某种方式声明此命名空间。所以您应该将图 21 中所示的三行代码添加到文件开始的命名空间定义部分。
图 21. xmldsig-core-schema
- 如果出现错误,提示存在重复命名空间定义,请打开 xenc-schema.xsd 模式,并修改导入命名空间,如图 22 和图 23 中所示。
图 22. xenc-schema
图 23. xenc-schema
这应该可以清除掉之前的所有错误(如果有)。

 |

|
定义中介模块
现在已经完成了准备工作,可以开始创建新中介模块并添加必要的中介原语。
- 选择 File > New > Project。然后从 Select a wizard 窗口选择 Mediation Module。
图 24. 新的中介模块
- 在 Module Name 字段键入
AsynchResSystemModule,并保留图 25 中所示的缺省设置。
图 25. 添加接口
- 单击 Next。在显示的 Select Required Libraries 窗口中选择 Asynch-Library,以将其添加到模块中,从而允许中介模块使用您之前在库中定义的数据类型和接口。
- 向导完成模块的创建后,请双击 Assembly Diagram 图标,以使用组装关系图。此时会打开 Assembly Editor。
- 通过将相关图标拖动到关系图上添加导入和导出组件。将其分别重命名为
WS_Export 和 JMS_Import。
- 右键单击导出组件,并选择 add interface,从而将
AsynchResSystemExport 接口添加到导出组件(请参见图 26),将 AsynchResSystemImport 接口添加到导入组件(请参见图 27)。
图 26. 添加导出接口
图 27. 添加导入接口
- 选择 Mediation Module 组件,并执行以下操作:
- 单击右键,选择 Add Interface 选项,并添加 AsynchResSystemExport 接口。
- 单击右键,选择 Add Reference 选项,并添加 AsynchResSystemImport 接口。
- 将模块重命名为
Asynch_Mediation。
接下来:
- 选择 WS_Export 组件,单击右键并选择 Wire to Existing 选项。
- 选择 JMS_Import 组件,单击右键并选择 Wire to Existing 选项。
完成了上述步骤后,您的组装关系图应该与图 28 所示类似。
图 28. 组装关系图
- 因为模块必须获得 SOAP/HTTP 消息并将其转换为 JMS 有效负载,所以应该生成两个绑定:
- 右键单击 WS_Export 组件,并选择 Generate Binding 选项。
- 从打开的窗口中,选择 Web Service Binding,然后在 Transport Selection 窗口中选择 SOAP/HTTP(请参见图 29)。
图 29. Transport selection
- 右键单击 JMS-Import 组件,再次选择 Generate Binding 选项。
- 选择 JMS Message。在打开的窗口中,选择 Publish-Subscribe 作为消息传递域,然后选中 Use pre-configured messaging provider resources 复选框,并提供根据在本系列的第一篇文章中已经执行的配置步骤提供主题名称和主题连接工厂设置。
图 30. 配置 JMS 导出
记得选择 Business Object XML using JMSTextMessage 选项作为序列化类型。这样可以确保 SOAP 消息的加密主体采用 XML 形式传递到主题,然后可以使用某个 XML 安全标准解密算法进行解析和重新构建(如本系列的第 2 部分中所述)。
- 完成了配置之后,导入和导出绑定就为此模块提供了中介流。为此,请右键单击模块组件,并选择 Generate Implementation,如图 31 中所示。
图 31. 生成实现
- 在出现的窗口中,选择 AsynchResSystemModule 并单击 OK(请参见图 32)。将生成新中介流。
图 32. 异步资源系统模块
- 在 Operation Connections 窗口中对 sendUpdateAgenda 和 publishAgenda 操作进行链接。
- 添加新 message setter 原语,并将其命名为
setMessageSelector。
- 添加 XSLT transformation 原语,并将其命名为
adaptInterfaces。
- 按照图 33 中所示对这些原语进行排序和连接。
图 33. 中介流
- 单击 setMessageSelector,并在页面底部的 Properties 窗口中选择 Details 选项卡。
- 单击 Add 按钮。
- 从 Type 下拉列表中选择 Copy。将显示两个 CustomXPath 按钮,可通过这两个按钮为 Target 和 Value 字段提供指导性 Xpath 表达式。
图 34. 消息选择器
- 在 Target 字段中选择 JMSType,在 Value 字段中选择 serviceproviderId。通过这样,
messageSetter 会将唯一地标识每个服务提供者的 serviceProviderId 字符串从消息的主体复制到 JMS Header,从而充当消息选择器,如本系列的第一篇文章中所述。
- 保存中介流,然后选择 adaptInterfaces XSLT transformation 原语。
- 在页面底部的 Properties 窗口中选择 Details 选项卡,然后单击 New 按钮,以创建新转换。
- 在显示的窗口中,保持默认设置,并单击 Finish。
图 35. XSLT 映射
- 在接下来显示的窗口中,展开两侧的目录树,直到找到
KeyInfo 元素为止。也请展开此元素。您应该看到右侧带有箭头的 ds:KeyName 元素。之所以显示箭头,是因为 KeyInfo 是通过 xmldsig 模式中的 Choice 构造定义的。
图 36. XSLT 映射
- 单击箭头,并向下滚动到
EncryptedKey 元素,然后在两侧选择此元素。我们在前面修改了 KeyInfo 复杂类型定义,以在 Choice 内添加 EncryptedKey 元素,现在您应该对此有了更好的理解。事实上,如果没有这个更改,您将无法从箭头选择 EncryptedKey 元素,因此,只要使用了该算法加密密钥和加密值,所有与密钥相关的信息都不会复制到 JMS 有效负载中(请参见图 37)。
图 37. 转换
- 在两侧选择 xenc:EncryptedData 元素,并单击鼠标右键,以选择 match mapping 选项。通过这样,可告知 WebSphere Enterprise Service Bus 将传入 SOAP 请求的主体的传入
EncryptedData 部分的全部内容递归复制到 JMS 有效负载中。
- 保存转换,并关闭窗口。
- 最后,保存整个中介流。

 |

|
结束语
本文详细说明了如何告知 WebSphere Enterprise Service Bus 接受包含数据加密部分的 SOAP 消息,执行协议切换,然后将这些消息转发到服务提供者注册到的 JMS 主题。您了解了如何进行以下工作:
- 恰当地定义导出接口,以获取包含敏感数据的 SOAP HTTP 消息。
- 配置消息选择器,以使用选择器信息充实 JMS 消息 Header。
- 引入 XSLT 转换,以匹配导入和导出接口,从而添加中介逻辑(甚至在消息包含加密数据的情况下也能使用)。
- 提供导出接口,以将敏感数据作为 JMS 有效负载发送到主题。
到目前为止,我们已经对整个场景进行了全面的讨论。本系列的最后一部分将讨论以下内容:
- 关于应用程序客户端的顾虑。
- 从 WebSphere Enterprise Service Bus 获取 JMS 消息。
- 使用服务提供者的私钥解密敏感数据,以重构从中央预约系统发送并通过 WebSphere DataPower SOA Appliances 计算单元进行了加密的原始消息。
这些内容将在本系列的第 4 部分(也是最后一部分)中进行深入讨论,敬请关注!
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Sample files | AsynchResSystemModuleApp_WSDLFiles.zip | 6KB | HTTP |
|---|
参考资料 学习
获得产品和技术
讨论
作者简介  | |  | Antonio Gallo 是在 Banca d'Italia 工作的 IT 专家。Antonio 从 2000 年起就是位于罗马的 Tivoli Lab 的成员,曾参与过讲座中心的各种活动,为客户提供关于 SOA 和 Web 服务如何用于实现其业务和技术目标并帮助他们实现第一个原型。他是 Sun 认证 J2EE 企业架构师 (Sun Certified J2EE Enterprise Architect),感兴趣领域包括软件设计模式、企业服务总线和 SOA。 |
 | |  | Maria Gallo 在罗马的 IBM 软件部 Tivoli Lab 担任软件开发人员。她拥有 10 年的 IT 从业经验,曾在变更和配置管理领域担任过不同的多种职位:客户支持、产品支持和开发。她感兴趣的主要领域有安全性和 J2EE 应用程序。她也是 Sun 认证 J2EE 企业架构师。 |
 | |  | Michele Crudele 在罗马的 IBM 软件部 Tivoli Lab 担任软件架构师。他拥有 15 年的 IT 从业经验,主要从事系统管理产品和解决方案的开发工作。Michele 曾从事过不同类别的工作,拥有广泛的技术经验,如变更配置管理、监视和可用性管理、IBM 自主计算技术及出版行业的数字资产管理。 |
对本文的评价
|