使用 WSE 2.0 从WS-Routing移动到WS-Addressing

 

Aaron Skonnard
北面大学

2004 年 4 月

适用于:
   适用于 Microsoft® .NET 的 Web 服务增强功能 2.0
   WS-Routing规范
   WS-Addressing规范

总结: 请参阅有关 Web 服务路由的问题和传输中性寻址的需求,特别是关注从WS-Routing转向新的WS-Addressing规范。 其中显示了核心WS-Addressing概念和使用 Web 服务增强功能 2.0 实现安全路由。 (21 个打印页)

目录

简介
传输中立性
传输依赖项
重新访问WS-Routing
“下一跃点”路由
输入 WS-Addressing
终结点引用
将终结点引用绑定到标头
WSE 2.0 中的WS-Addressing
使用 WSE 2.0 进行路由
使用 WSE 2.0 进行安全路由
我们在哪?
参考
相关书籍

简介

本文介绍与 Web 服务路由相关的问题,以及传输中性寻址的需求,特别侧重于从WS-Routing转向新的 WS 寻址 规范。 在此过程中,我们将介绍核心WS-Addressing概念,并演示如何使用 Web 服务增强 (WSE) 2.0 实现安全路由。

传输中立性

在深入了解WS-Addressing和路由的螺母和 Bolt 之前,请务必了解一个关键 Web 服务概念,该概念促使 SOAP 和各种分层 WS-* 规范(包括 WS-Addressing)的设计。 该概念是 传输中立性

尽管大多数开发人员认为 Web 服务本质上与 HTTP 相关联,但基本体系结构和更高级的层设计为与传输无关。 可以在 soap:Envelope> 元素中看到<这一点的证据,该元素提供了一个框架,用于将 XML 有效负载与随附的标头分开:

<soap:Envelope 
  xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <!-- headers go here -->
  </soap:Header>
  <soap:Body>
    <!-- payload goes here -->
  </soap:Body>
</soap:Envelope>

SOAP 对有效负载和标头的区别使捕获应用程序协议信息成为可能,而无需创建对传输协议的依赖关系。 只要发送方和接收方共同了解 SOAP 消息中放置的 XML 标头,他们就可以通过各种不同的传输来交换 SOAP 消息。

传输依赖项

尽管关注传输中立性,但当今的大多数 SOAP 基础结构不提供引用终结点和调度消息的机制,而无需传输协议的帮助。

例如,使用 SOAP over HTTP 时,HTTP 请求消息的目标 URI 表示 SOAP 终结点的地址。 这是引用终结点地址的唯一位置。 消息到达处理后,SOAP 基础结构将使用 HTTP SOAPAction 标头来确定响应消息时应发生的情况。 大多数 SOAP 实现使用此信息将消息调度到特定方法 (请参阅图 1) 。

图 1. SOAP 地址和操作

在传输协议中放置此信息会将 SOAP 路由和调度与传输细节联系在一起,因此对开发人员提出了更多要求。 如果要通过其他传输发送此消息,则必须找到一种方法在新协议中携带相同的信息,而不是以标准方式提及。 此外,将信息放入传输协议中是消息在其旅程的不同部分使用不同的传输协议的障碍:例如,一个腿使用 HTTP,另一个使用电子邮件。 最后,应用于 SOAP 消息的安全机制不会在传输协议中保护消息外部的信息。

在 SOAP 标头部分中携带此信息更独立、更可重用且更安全。 这将使 SOAP 基础结构能够适应更广泛的传输范围,同时简化编程模型。 最终,删除传输依赖项将整体提高 SOAP 的简单性和灵活性。

重新访问WS-Routing

WS-Routing是第一个解决此问题的规范。 WS-Routing提供了以非传输方式指定消息路由和调度信息的功能。 有关其他背景信息,请查看 使用 Web 服务增强功能 1.0 路由 SOAP 消息

规范定义了一个名为 r:path> 的新元素 (<,) 要在 SOAP 标头块中使用。 path 元素具有多个可用于指定路由和调度信息的子元素,包括 <r:to><r:action>。 这些元素可用于捕获与之前相同的信息,但与传输协议没有任何关系,如图 2 所示。

图 2. WS-Routing路径标头

除了 <r:to> 和 <r:action> 之外,WS-Routing还定义了多个为更复杂的消息路由方案设计的可选元素。 代码列表 1 显示由星号“*”WS-Routing (定义的完整 r:path> 结构<,表示) 可以有多个匹配项。

代码列表 1。 WS-Routing“path”元素的结构

<s:Envelope
   xmlns:s="https://schemas.xmlsoap.org/soap/envelope/"
>
  <s:Header>
    <!-- WS-Routing -->
    <r:path xmlns:r="https://schemas.xmlsoap.org/rp">
       <r:action />
       <r:to />
       <r:fwd>
         <r:via /> *
       </r:fwd>
       <r:rev>
         <r:via /> *
       </r:rev>
       <r:from />
       <r:id />  
       <r:relatesTo />
       <r:fault />
    </r:path>
    ...

这些元素允许消息描述其自己的路由。 消息可以定义 r:fwd>) (<转发路径、r:rev (< r:rev>) 对应响应消息的反向路径,以及将 (<r:id><r:relates to>) 的消息关联的方式。 设计为处理路径信息的路由器必须先更改WS-Routing标头,然后才能将消息发送到路径中的下一个节点。 例如,路由器必须删除第一个 <r:via> 元素,并将消息转发到由下一个 <r:via> 元素标识的节点。 这一过程一直持续到消息到达由 r:to> 元素标识的<节点。 路由器也可能在此过程中构建反向路径。

尽管这种消息内路由功能提供了一些有趣的可能性,但它也带来了一些严重的安全挑战。 路由器必须修改标头这一事实使消息签名复杂化。 原始发件人不能对邮件进行签名 (包括WS-Routing标头) ,并通过WS-Routing路径发送邮件,而不会破坏原始签名。

加密在路由方面引入了一系列类似的挑战,因为路由器需要读取、修改消息和标头,然后重新加密消息和标头,然后再将其发送。 中间人需要所需的安全令牌才能读取、签名和重新加密消息,这样才能正常工作。 这本身就是一个挑战。

可以避免对WS-Routing标头进行签名和加密,但随后会打开系统进行攻击。 这些安全挑战促使采用更简单的基于 SOAP 的路由方法。

“下一跃点”路由

简化WS-Routing并缓解上述安全挑战的一种简单方法是避免使用 (r:fwd> 和 <r:rev>) 路径<元素。 避免这些元素无需中介修改消息。

有些人可能认为丢失消息内路径信息是一个很大的牺牲,但另一些人会争辩说,无论如何,它都不是实现路由的正确方法。 其参数的基础是发送方不必知道生成消息路径所需的体系结构详细信息。 相反,发送方应只需了解单个终结点,后者可以在闭门后处理其他路由需求。 可以将其视为 “下一跃点”路由

“下一跃点”路由实质上是 TCP/IP 的工作方式。 TCP/IP 消息包含有关消息来自何处和去向的信息,但不包含有关消息如何到达该消息的详细信息。 当 TCP/IP 消息通过网络传输时,每个节点都会检查 TCP/IP 标头以查看其走向,然后将消息发送到离目标更近的下一个 TCP/IP 节点。 这会一直持续到节点到达其目标。

这解释了 WS-Addressing 设计背后的一些原因,该设计提供安全的“下一跃点”路由机制。

输入 WS-Addressing

作为 WS 路由的改进,WS-Addressing提供了一种用于处理 Web 服务的非传输机制。 WS-Addressing形式化了上述WS-Routing的简化,并添加了一些我们将在下面介绍的其他功能。

WS-Addressing将正式删除与消息路径相关的WS-Routing元素, (包括 <r:path>、 <r:fwd> 和 <r:rev>) ,并假定用户将依赖“下一跃点”方法满足路由需求。 WS-Addressing 定义的大多数元素在语义上与 WS 路由中最初定义的元素等效。

表 1 描述了WS-Addressing消息信息标头,并显示了它们如何映射到其WS-Routing前置任务。 所有这些元素都与由以下 URI 标识的 WS-Addressing 命名空间相关联: https://schemas.xmlsoap.org/ws/2003/03/addressing

表 1. WS-Addressing消息信息标头

名称 WS-Routing前置任务 类型 说明
wsa:MessageID r:path/r:id xsd:anyURI 在时间和空间中唯一标识此消息的 URI。
wsa:RelatesTo r:path/r:relatesTo xsd:anyURI 一对值,指示此消息与另一条消息的关系。 关系的类型由 QName 标识。 相关消息由对应于相关消息的 MessageID 值的 URI 标识。 答复消息必须包含 由 wsa: Reply 和请求消息的消息 ID 属性组成的 wsa: RelatesTo 标头。
wsa:To r:path/r:to xsd:anyURI 此消息的预期接收方的地址。
wsa:Action r:path/r:action xsd:anyURI 唯一 (和不透明) 标识此消息所暗示语义的标识符。
wsa:From r:path/r:from endpoint-ref 消息源自的终结点的引用。
wsa:ReplyTo 不适用 endpoint-ref 一个终结点引用,用于标识对此消息的回复的预期接收方。 如果需要答复,则消息必须包含 wsa:ReplyTo 标头。 发件人必须使用 wsa:ReplyTo 标头的内容来构建答复消息。 如果缺少 wsa:ReplyTo 标头,则 wsa:From 标头的内容可用于向源构建消息。 如果邮件没有有意义的回复,则此属性可能不存在。 如果此属性存在,则 wsa:MessageID 标头为 REQUIRED。
wsa:FaultTo 不适用 endpoint-ref 一个终结点引用,用于标识与此消息相关的错误的预期接收方。 在表述错误消息时,发送方必须使用此引用的内容来表述错误消息。 如果缺少此引用,则发送方可以使用 wsa:ReplyTo 的内容来表述错误消息。 如果此引用和 wsa:ReplyTo 都不存在,则发送方可以使用 wsa:From 的内容来表述错误消息。 如果存在此属性,则 [message id] 属性为 REQUIRED。

使用 wsa:To> 指定消息的目标,使用<<wsa:Action> 指定操作,并使用 wsa:MessageID 为消息指定唯一 ID<>。 如果是回复消息,则使用 <wsa:RelatesTo> 标头及其 RelationshipType 属性指示其与请求消息的关系。

由于WS-Addressing远离消息路径,因此它不会定义另一个容器元素(如 <r:path> ), (请参阅代码列表 1) 。 相反,WS-Addressing元素只是作为 soap:Header> 的直接子级<放置。 图 3 说明了如何将WS-Routing信息映射到 WS-Addressing。

图 3. 将WS-Routing映射到WS-Addressing

使用 时,请求消息中仅 <需要 wsa:To> 和 <wsa:Action> ,WS-Addressing (其余元素是可选的) 。 支持WS-Addressing的 SOAP 基础结构应基于这两个值调度消息。 还可以使用这两个值实现简单的“下一跃点”路由机制。 可以将 <wsa:To> 视为逻辑地址,并提供到中间路由节点上物理地址的简单转换, (稍后) 。

除了 WS 路由中传递的内容外,WS-Addressing还引入了一种新的机制,用于以标准、语义丰富的方式引用终结点。 这样就可以在消息中传输终结点引用, (认为 通过引用) 传递 ,从而向接收方指示将来发送消息的位置。 WS-Addressing为此引入了名为 终结点引用的新架构类型。

终结点引用

在 WS 路由中, <r:from> 只是一个 URI。 这样就可以在邮件中传递发件人的地址。 然后,接收方可以将响应消息发送回发件人的地址。 这为在消息中传递终结点引用提供了有限的机制。 但是,若要使用 r:from> 引用<的服务,接收方必须提前知道各种服务详细信息, (例如服务协定和策略) 。

在 WS-Addressing 中 <,wsa:From> 元素的类型为 endpoint reference。 通过终结点引用,可以随地址一起传递其他终结点元数据。 理想情况下,终结点引用将包含足够的信息,供使用者自动协商交互。

为实现此目的,终结点引用必须包含地址以及其他允许发现协定详细信息和策略的属性。 这些附加属性可能包括服务名称、端口名称、端口类型以及描述服务的要求、功能和首选项的WS-Policy语句。 引用还应能够根据需要保存任意数量的特定于应用程序的属性。

WS-Addressing规范定义了一个复杂类型定义,该定义为终结点引用信息提供结构。 其名称为 wsa:EndpointReferenceType (请参阅代码列表 2) 。

代码列表 2:WS-Addressing XML 架构定义

... 
<xs:complexType name="EndpointReferenceType">
  <xs:sequence>
    <xs:element name="Address" type="wsa:AttributedURI" /> 
    <xs:element name="ReferenceProperties" 
      type="wsa:ReferencePropertiesType" minOccurs="0" /> 
    <xs:element name="PortType" type="wsa:AttributedQName" 
      minOccurs="0" /> 
    <xs:element name="ServiceName" type="wsa:ServiceNameType"   
      minOccurs="0" /> 
    <xs:any namespace="##other" processContents="lax" 
      minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:anyAttribute namespace="##other" processContents="lax" /> 
</xs:complexType>

<xs:element name="EndpointReference" 
  type="wsa:EndpointReferenceType"/> 
...

<wsa:Address> 是 wsa:EndpointReferenceType 中唯一必需的元素。 <wsa:ReferenceProperties> 元素基本上是其他自定义属性的容器, (它保存) 的 xsd:any 元素序列。 <wsa:ServiceName> 元素附带 PortName 属性,即使代码清单 2 中未显示它。 wsa:ServiceName> 之后<的 xsd:any 序列是可以放置其他元素的扩展点。 这是放置策略元素的位置。 有关每个构造的完整说明,请参阅表 2。

表 2:EndpointReferenceType 元素

名称 说明
地址 标识终结点的地址 URI。 这可能是网络地址或逻辑地址。
ReferenceProperties 引用可能包含标识要传达的实体或资源所需的多个单独属性。
PortType 要传递的终结点的主 portType 的 QName。
ServiceName 这是标识 WSDL 服务元素的 QName,其中包含要传达的终结点的定义。 服务名称提供指向服务终结点的完整说明的链接。 可选的非限定名称标识服务中与终结点对应的特定端口。
[policy] 一个可变数量的 XML 策略元素,如 WS-Policy 中所述,用于描述终结点的行为、要求和功能。 策略可以包含在终结点中,以便于使用方应用程序更轻松地处理,或者因为策略是动态生成的。

WS-Addressing架构还定义了 wsa:EndpointReferenceType 类型的名为 <wsa:EndpointReference> 的元素 (请参阅代码清单 2) 。 下面显示了完整的 <EndpointReference> 示例:

<wsa:EndpointReference xmlns:c="http://example.org/claims"
  xmlns:p="https://schemas.xmlsoap.org/ws/2002/12/policy"
>
  <wsa:Address>http://claimserver/ins/p.asmx</wsa:Address>
  <wsa:ReferenceProperties>
    <c:PatientProfile>123456</c:PatientProfile>
    <c:CarrierID>987654</c:CarrierID>
  </wsa:ReferenceProperties>
  <wsa:PortType>c:ClaimsPortType</wsa:PortType>
  <wsa:ServiceName PortName="c:ClaimsSoapPort">c:ClaimsService
</wsa:ServiceName>
  <p:Policy>
    ... <!-- policy statement omitted for brevity --> 
  </p:Policy>
</wsa:EndpointReference>

无需在所有情况下都使用 <wsa:EndpointReference> 元素。 为了方便起见,架构中提供了它。 可以定义 wsa:EndpointReferenceType 类型的新元素。 这正是表 1 中显示的最后三个消息信息标头 (<wsa:From><wsa:ReplyTo><wsa:FaultTo>) 的定义方式。

与之前一样, <wsa:From> 是对发起消息的终结点的引用。 当 wsa:ReplyTo> 不存在时<,接收方应将响应消息发送到此终结点。 请务必注意,NAT、DHCP 和防火墙等各种网络技术使环境难以将有意义的地址分配给发送节点。 WS-Addressing定义用于标识这些“匿名”终结点的已知 URI: https://schemas.xmlsoap.org/ws/2003/03/addressing/role/anonymous。 当应用程序使用此值时,它们必须提供一些用于中继响应消息的其他超出边界的机制。

<wsa:ReplyTo> 元素是对应发送答复消息的终结点的引用,而 <wsa:FaultTo> 元素是对应发送与消息相关的错误的终结点的引用。 这意味着其中每个元素都可以包含一个结构,如上所示。

代码列表 3 显示了一个示例,该示例使用 wsa:EndpointReferenceType 类型的一些消息头。

代码列表 3:完成WS-Addressing示例

<s:Envelope xmlns:s="..." xmlns:wsa="...">
  <s:Header>
    <wsa:Action>http://skonnard.com/SubmitClaim</wsa:Action>
    <wsa:To>http://skonnard.com/Claims/Submit.asmx</wsa:To>
    <wsa:From>
      <wsa:Address>http://skonnard.com/main/sub.asmx</wsa:Address>
      <wsa:ReferenceProperties>
        <c:PatientProfile>123456</c:PatientProfile>
        <c:CarrierID>987654</c:CarrierID>
      </wsa:ReferenceProperties>
    </wsa:From>
    <wsa:ReplyTo>
      <wsa:Address>http://skonnard.com/resp/resp.asmx</wsa:Address>
      <wsa:ReferenceProperties>
        <c:PatientProfile>123456</c:PatientProfile>
        <c:CarrierID>987654</c:CarrierID>
      </wsa:ReferenceProperties>
    </wsa:ReplyTo>
    <wsa:FaultTo>
      <wsa:Address>http://skonnard.com/fault/err.asmx</wsa:Address>
      <wsa:ReferenceProperties>
        <c:PatientProfile>123456</c:PatientProfile>
        <c:CarrierID>987654</c:CarrierID>
      </wsa:ReferenceProperties>
    </wsa:FaultTo>
  </s:Header>
  <s:Body xmlns:c="http://example.org/claims">
    <c:SubmitClaim> ... </c:SubmitClaim>
  </s:Body>
</s:Envelope>

如你所看到的,终结点引用可能包含的不仅仅是一个地址。 这些附加信息使节点能够以丰富的方式与其他终结点协商交互。

将终结点引用绑定到标头

当应用程序决定使用终结点引用描述的终结点时,它必须使用绑定将终结点引用中的信息映射到相应的消息标头。

WS-Addressing规范仅定义 SOAP 消息的单个绑定。 SOAP 绑定声明 address 属性映射到 <wsa:To> 标头,每个引用属性都成为独立的标头块,如图 4 所示。

图 4。 终结点引用 SOAP 绑定

WSE 2.0 中的WS-Addressing

WSE 2.0 中最基本的更改之一是它放弃了对WS-Routing的支持,并添加了对 WS 寻址的支持。 WSE 2.0 为 Microsoft.Web.Services.Addressing 命名空间中的WS-Addressing提供各种新类。 整个消息 API 已围绕终结点引用而不是 URI 进行了修改。 WSE 2.0 引入了名为 EndpointReference 的新类,该类替换了整个 WSE 2.0 API 中的 System.Uri

例如, SoapSenderSoapReceiver 类现在直接处理 EndpointReference 对象。 以下代码片段演示如何在基于 TCP 的简单聊天应用程序中将 EndpointReference 对象与 SoapSender 类一起使用:

...
SoapEnvelope env = new SoapEnvelope();
env.Context.Addressing.Action = String.Format("urn:chat:message");
EndpointReference epr = 
  new EndpointReference("soap.tcp://askonnard:123/aaron"));
env.Context.Addressing.ReplyTo = new ReplyTo(epr);
env.CreateBody(); // must create body before setting it
env.Body.InnerXml = String.Format(
  "<x:message xmlns:x='urn:chat'><user>{0}</user><msg>{1}</msg>
</x:message>", user, msg);
...
EndpointReference epr = new EndpointReference(
   new Uri("soap.tcp://askonnard:456/monica"));
SoapSender ss = new SoapSender(epr);
ss.Send(env);
...

每当使用 WSE 2.0 发送消息时,它都会自动添加所需的WS-Addressing消息信息标头。 例如,前面的代码片段将生成以下 SOAP 消息:

<soap:Envelope  
  xmlns:wsa="https://schemas.xmlsoap.org/ws/2003/03/addressing"   
  xmlns:wsse="https://schemas.xmlsoap.org/ws/2003/06/secext"   
  xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsa:Action>urn:chat:message</wsa:Action>
    <wsa:ReplyTo>
      <wsa:Address>soap.tcp://askonnard:123/aaron</wsa:Address>
    </wsa:ReplyTo>
    <wsa:MessageID>uuid:59bc1ebb-40aa-4508-9a69-5b148d04d697
    </wsa:MessageID>
    <wsa:To>soap.tcp://askonnard:456/monica</wsa:To>
    ...
  </soap:Header>
  <soap:Body>
    <x:message xmlns:x="urn:chat">
      <user>aaron</user>
      <msg>hi</msg>
    </x:message>
  </soap:Body>
</soap:Envelope>

在前面的示例中,EndpointReference 对象仅包含一个地址。 可以使用其他属性填充 EndPointReference,如下所示:

...
EndpointReference epr = new EndpointReference(
   new Uri("soap.tcp://askonnard:456/monica"));
epr.ServiceName = new ServiceName(
   new XmlQualifiedName("WseChat", "urn:chat"));
epr.ServiceName.PortName = "ChatPort";
epr.PortType = new PortType(
   new XmlQualifiedName("WseChatSoapPort", "urn:chat"));

// set some custom reference properties...
epr.ReferenceProperties = new ReferenceProperties();
epr.ReferenceProperties.LoadXml(GetReferenceProperties());

env.Context.Addressing.ReplyTo = new ReplyTo(epr);
...

发送此 SoapEnvelope 时,WSE 基础结构生成以下 SOAP 消息:

<soap:Envelope 
 xmlns:wsa="https://schemas.xmlsoap.org/ws/2003/03/addressing"   
 xmlns:wsse="https://schemas.xmlsoap.org/ws/2003/06/secext" 
 xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsa:Action>urn:chat:message</wsa:Action>
    <wsa:MessageID>uuid:7e44dd92-ec1a-4b75-aa5d-8744698a5d39
    </wsa:MessageID>
    <wsa:ReplyTo>
      <wsa:Address>soap.tcp://localhost:123/aaron</wsa:Address>
      <wsa:ReferenceProperties>
        <x:MyHeader1 xmlns:x="urn:example">Foo</x:MyHeader1>
        <x:MyHeader2 xmlns:x="urn:example">Bar</x:MyHeader2>
      </wsa:ReferenceProperties>
      <wsa:PortType xmlns:prefix0="urn:chat"
      >prefix0:WseChatSoapPort</wsa:PortType>
      <wsa:ServiceName wsa:PortName="ChatPort" 
       xmlns:prefix1="urn:chat">prefix1:WseChat</wsa:ServiceName>
    </wsa:ReplyTo>
    <wsa:To>soap.tcp://askonnard:456/monica</wsa:To>
    ...
  </soap:Header>
  <soap:Body>
    <x:message xmlns:x="urn:chat">
      <user>aaron</user>
      <msg>hi</msg>
    </x:message>
  </soap:Body>
</soap:Envelope>

然后,在 SoapReceiver 实现中,可以使用 <wsa:ReplyTo> 引用作为响应消息的目标:

public class ChatReceiver : SoapReceiver
{
   protected override void Receive(SoapEnvelope e)
   {
      // extract message fields from SOAP envelope
      SoapSender ss = new SoapSender(e.Context.Addressing.ReplyTo);
      ... // send response message

   }
}

WSE 基础结构将自动应用 SOAP 终结点引用绑定,并将 <wsa:ReplyTo> 信息映射到相应的消息标头。 在这种情况下,响应消息如下所示:

<soap:Envelope 
 xmlns:wsa="https://schemas.xmlsoap.org/ws/2003/03/addressing"   
 xmlns:wsse="https://schemas.xmlsoap.org/ws/2003/06/secext" 
 xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <wsa:Action>urn:chat:message</wsa:Action>
    <wsa:MessageID>uuid:7e44dd92-ec1a-4b75-aa5d-8744698a5d40
    </wsa:MessageID>
    <x:MyHeader1 xmlns:x="urn:example">Foo</x:MyHeader1>
    <x:MyHeader2 xmlns:x="urn:example">Bar</x:MyHeader2>
    <wsa:To>soap.tcp://askonnard:123/aaron</wsa:To>
    <wsa:RelatesTo RelationshipType="wsa:Reply">
      7e44dd92-ec1a-4b75-aa5d-8744698a5d39
    </wsa:RelatesTo>
    ...
  </soap:Header>
  <soap:Body>
    <x:message xmlns:x="urn:chat">
      <user>aaron</user>
      <msg>hi</msg>
    </x:message>
  </soap:Body>
</soap:Envelope>

请注意, <wsa:ReplyTo> 地址已映射到 <wsa:To> 标头,自定义引用属性成为 (<x:MyHeader1> 和 <x:MyHeader2>) 的独立标头块。

使用 WSE 2.0 进行路由

可通过多种方法使用 WS-Addressing 和 WSE 2.0 实现“下一跃点”路由。 一种方法是将 wsa:To> 地址简单转换为<另一个地址。 WS-Referral为这种类型的地址转换提供了一种机制。

以下 WS-Referral 语句指示应将目标 http://skonnard.com/Claims/Submit.asmx 消息路由到 http://claimserver/ins/sub.asmx 进行处理:

<!-- referralCache.config -->
<r:referrals 
  xmlns:r="https://schemas.xmlsoap.org/ws/2001/10/referral">
  <r:ref>
    <r:for>         
      <r:exact>http://skonnard.com/Claims/Submit.asmx</r:exact>
    </r:for>
    <r:if />
    <r:go>
      <r:via>http://claimserver/ins/sub.asmx</r:via>
    </r:go>
  </r:ref>
</r:referrals>

WSE 2.0 通过 Microsoft.Web.Services.Messaging.SoapHttpRouter 处理程序支持基于引用的路由。 可以通过将以下部分添加到 web.config 文件来配置终结点以将此处理程序与引用缓存一起使用 (注意:为提高) 的可读性,添加了代码换行符:

<configuration>
  <configSections>
    <section name="microsoft.web.services" 
      type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, 
      Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral, 
      PublicKeyToken=31bf3856ad364e35" />
  </configSections>
  <system.web>
    <webServices>
      <soapExtensionTypes>
        <add type="Microsoft.Web.Services.WebServicesExtension, 
      Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral, 
      PublicKeyToken=31bf3856ad364e35" priority="1" group="0" />
      </soapExtensionTypes>
    </webServices>
    <httpHandlers>
      <add type="Microsoft.Web.Services.Messaging.SoapHttpRouter, 
      Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral, 
      PublicKeyToken=31bf3856ad364e35" path="*.ashx" verb="*" />
    </httpHandlers>
  </system.web>
  <microsoft.web.services>
    <referral>
      <cache name="referralCache.config" />
    </referral>
  </microsoft.web.services>
</configuration>              

向此虚拟目录中的 .ashx 终结点发送消息时, SoapHttpRouter 将检查WS-Referral缓存以确定下一跃点的地址。 wsa <:To> 地址 https://localhost/endpoints/echo.ashx 为 的消息将按照 WS-Referral 语句的指示自动路由到 http://claimserver/ins/sub.asmx

实现“下一跃点”路由的另一种方法是编写自定义路由器类,用于检查消息的内容以确定路由决策。 这称为 基于内容的路由。 有关更多详细信息,请参阅 WSE 2.0 文档。

使用 WSE 2.0 安全路由

现在,WSE 2.0 支持 WS 寻址,你可以安全地对 SOAP 消息进行签名和加密,而不会面临 WS 路由带来的挑战。 这是因为WS-Addressing标头是不可变的,它们不供中介修改。 因此,你可以对邮件(包括WS-Addressing标头)进行签名和加密,以根据需要实现适当的安全级别。

以下示例演示如何使用 WSE 2.0 代理类对整个 SOAP 消息进行签名:

...
MyClaimsService e = new MyClaimsService();
e.RequestSoapContext.Security.Tokens.Add(GetSecurityToken());
e.RequestSoapContext.Security.Elements.Add(
  new Signature(tok));
e.Submit(claim);
...

此代码生成的已签名消息可以使用上一部分所述的技术进行路由,但现在以安全的方式进行路由。 强烈建议 (签名,并在必要时) 可能危及系统安全的WS-Addressing标头进行加密。

我们在哪?

在本文中,我们讨论了WS-Addressing的需求以及退出 WS 路由的原因。 我们讨论了WS-Addressing如何允许使用标准WS-Security技术安全地路由消息。 WSE 2.0 为WS-Addressing和“下一跃点”路由提供完全支持。

参考

Web 服务寻址 (WS-Addressing) 规范

使用 WS-Addressing 扩展 Web 服务的通信功能

SOAP 版本 1.2 第 1 部分:消息传递框架

Web 服务增强功能:了解适用于 .NET 企业应用程序的 WSE

了解 Web 服务规范和 WSE