策略文件基于 WS-Policy 規范,該規范是為允許 Web 服務聲明傳入消息有關安全性等方面的要求而創建的。如果希望簽名或者加密所有或部分消息,WSE 2.0 允許我們控制 Web 服務的用戶在消息中使用的安全令牌類別,以及控制對接收消息時限的限制,甚至可以為傳入的消息指定角色成員限制。
以下策略文件說明 Web 服務接收的消息應使用 Kerberos 令牌對消息主体進行簽名。
<?xml version="1.0" encoding="utf-8"?>
<policyDocument
xmlns="http://schemas.microsoft.com/wse/2003/06/Policy">
<mappings
xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy">
<mapDefault
policy="#policy-5903e02b-9c11-4dc5-8ca0-42d4e9d0bcde" />
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility">
<wsp:Policy
wsu:Id="policy-5903e02b-9c11-4dc5-8ca0-42d4e9d0bcde"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsse:Integrity wsp:Usage="wsp:Required"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:TokenInfo>
<SecurityToken
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:TokenType>wsse:Kerberosv5ST</wsse:TokenType>
</SecurityToken>
</wsse:TokenInfo>
<wsse:MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</wsse:MessageParts>
</wsse:Integrity>
</wsp:Policy>
</policies>
</policyDocument>
policyDocument 根元素有兩個子元素﹕mappings 和 policies。policies 元素含有一個或多個表示特定要求集的 Policy 元素。在示例中,策略包含一個 Integrity 要求,表示該消息需要數字簽名。TokenInfo 元素包含關于所需令牌种類的信息,本示例中為 Kerberos 令牌。最后,這一特定完整性要求指出必須簽名的文檔部分為正文,這是使用 MessageParts 元素指示的。
policyDocument 的 mappings 部分僅將特定終結點与 policies 部分中的策略關聯。本示例不包括特定終結點的任何映射,僅包括單一的默認映射。
除了實際創建策略文件以外,還需要讓 WSE 程序庫知道該策略的存在。因此,有必要配置 Web 服務以使用創建的策略文件。為此,需要修改 Web.config 文件。下面的 Web.config 文件給出了為啟用 WSE SoapExtension、啟用 WSE 配置部分中的處理程序以及添加接收策略緩存而作的更改。
<?xml version="1.0" encoding="utf-8"?>
<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>
<!-- 添加 WSE SoapExtension。請注意,
類型名稱要換行以便于閱讀并且
不應包含換行符。-->
<add type="Microsoft.Web.Services
.WebServicesExtension, Microsoft.Web.Services,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
priority="1" group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
<!-- WSE Configuration Section -->
<microsoft.web.services>
<policy>
<receive>
<cache name="policyCache.xml" />
</receive>
</policy>
</microsoft.web.services>
</configuration>
至此,已將 Web 服務配置成只接受符合 policyCache.xml 文件中策略要求的請求。
如果需要讓管理員為特定的 Web 服務配置策略,我們同樣希望對使用 Web 服務的應用程序進行類似配置。總而言之,如果管理員更改策略后我們必須重新生成使用的應用程序,則并沒有完全實現配置消息要求時無需重新生成 Web 服務的功能。
要為使用的應用程序添加該功能來發送符合特定策略的消息,需要本地具有該程序可以使用的策略文件。對于要調用 .asmx Web 服務的 Rock Paper Scissors 對等應用程序,我們只是將 policyCache.xml 文件复制到該可執行程序的工作目錄。如同對 Web 服務的處理,將該應用程序配置成使用其 .config 文件中的策略文件(本示例中為 RockPaperScissors.exe.config)。該配置文件如下所示。
<?xml version="1.0" encoding="utf-8"?>
<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>
<microsoft.web.services>
<policy>
<send>
<cache name="policyCache.xml" />
</send>
</policy>
</microsoft.web.services>
</configuration>
對等應用程序將通過發送符合 policyCache.xml 文件中的要求的消息与 Web 服務進行通信。
WSE 2.0 尋址
WSE 1.0 与 WSE 2.0 之間的區別之一是對 WS-Addressing 的支持。WS-Addressing 替換了 WSE 1.0 中支持的 WS-Routing 規范的大部分功能。從功能方面來說,WS-Addressing 不是將重點放在路由路徑上,而是提供一种机制將 To 和 From 標頭添加到 SOAP 信封中。WS-Addressing 也支持 Action、ReplyTo 和 FaultTo 標頭。Action 標頭類似于通過 HTTP 發送 SOAP 消息時通常使用的 SOAPAction HTTP 標頭。對于 .asmx Web 服務,HTTP SOAPAction 標頭用于确定接收傳入消息時應調用服務的哪种 Web 方法。与此類似,Action SOAP 標頭用于确定通過非 HTTP 傳輸接收消息時要調用的函數。
在 Rock Paper Scissors 應用程序中,我們還將利用 ReplyTo 標頭來确定接收下一消息的地址。當對等應用程序之一向 RPSService 發送單向 RegisterPlayer 消息時,將指定一個 ReplyTo 終結點,指示對等通信開始時用來接收對方發送的消息的地址。与此類似,當第二個對等應用程序將 FindPlayer 消息發送到 RPSServer 時,RPSServer 將返回一個帶有 ReplyTo 標頭的消息,該標頭指示第一個對等應用程序的終結點。這就告訴第二個對等應用程序應該將自己的下一消息發送到第一個對等應用程序的終結點。在余下的對等消息中,繼續指定 ReplyTo 標頭來不斷指示接收下一消息的地址。
下面是對等應用程序使用的部分代碼,在代碼中,首先偵听對等通信,然后在調用 RPSServer RegisterPlayer Web 方法之前通過 ReplyTo 標頭指示 URI。
myPeerUri
= new Uri("soap.tcp://"
+ System.Net.Dns.GetHostName()
+ ":3131/RPSPeer1");
SoapReceivers.Add(myPeerUri, typeof(PeerService));
RPSServ.RPSServerWse proxy = new RPSServ.RPSServerWse();
proxy.RequestSoapContext.ReplyTo = myPeerUri;
TCP 消息處理
在 WSE 2.0 中,消息處理是新增功能的主要部分。WSE 2.0 通過异步 TCP 或請求/響應方式 TCP 為進程中的通信提供支持。在本示例的 Rock Paper Scissors 應用程序中,我們將發送消息來指示玩家對于特定游戲實例是否選擇了石頭、布或剪刀。由于我們依靠用戶交互來确定發送消息的內容,我們不可能無限地等待需要發送響應的請求,因此,我們使用异步 TCP 消息來實現特定游戲的通信。一個人發送其動作后應用程序耐心的等待,直到對方玩家發送其動作。您可以將這看作類似于向倉庫發送發貨單,必須等待,直到有人手動包裝材料,才能發送一個指示請求完成的響應。