使用 Web Services Enhancements 2.0 進行編程

來源:互聯網
上載者:User
services|web|編程  

單擊下載原始碼,可以從 Microsoft Download Center 下載 Rock Paper Scissors 應用程式的原始碼。

目錄

  • Rock Paper Scissors: 一種安全的、分布式訊息處理應用程式範例
  • 與 Windows 安全性整合的 Kerberos 令牌支援
  • 安全性原則
  • WSE 2.0 定址
  • TCP 訊息處理
  • WSE 2.0 的其他功能
  • 小結

Microsoft 發行了 Web Services Enhancements (WSE) 1.0 版,以在支援的產品中啟用安全、路由和附件,同時它還支援進階 Web 服務。Web Services Enhancements 2.0(英文)已從簡單支援基本協議發展到支援核心功能與作業系統的整合,並增強了策略、信任和上下文令牌功能。

WSE 也是對 .NET Framework 支援的擴充,它用於建立和使用 Web 服務,而 WSE 2.0 採用新的編程模式。過去,Web 服務支援一直依賴 Internet Information Server (IIS) 作為其 HTTP 伺服器主機;現在,WSE 2.0 支援通過 TCP/IP 或在進程內來發送訊息。這樣,您可以通過對等、單向、非同步等方式將訊息從伺服器發送到用戶端。

下面,我們將簡要介紹 WSE 2.0 的幾個主要功能,並假設您已熟悉 WSE 1.0。有關 WSE 1.0 的詳細資料,請參閱 Programming with Web Services Enhancements 1.0 for Microsoft .NET(英文)。

Rock Paper Scissors:一種安全的、分布式訊息處理應用程式範例

為了展示 WSE 2.0 的各個方面,我想建立一個應用程式以展示一些新安全功能和訊息處理功能。具體來說,我喜歡使用 TCP 訊息處理支援來顯示對等通訊,並使它在 Windows 安全性領域工作。我想到的是一個簡單的分布式版本的舊 Rock Paper Scissors 遊戲,現在可以用 WSE 2.0 進行安全分發。

Rock Paper Scissors 是一個兩人兒童遊戲,傳統上包括讓每個孩子拍手三次,在第三次拍手時出示石頭、剪刀或布的形狀。根據下表中所示理由決定勝者:

 石頭布剪刀石頭 平局布裹石頭。
布方贏!石頭砸壞剪刀。
石頭方贏!布 布裹石頭。
布方贏!平局剪刀剪開布。
剪刀方贏!剪刀 石頭砸壞剪刀。
石頭方贏!剪刀剪開布。
剪刀方贏!平局

該遊戲通常用於確定由誰先選擇參加沙地棒球賽的選手、誰吃最後的冰淇淋,甚至由誰擊打對方的手臂。

我們將 Rock Paper Scissors 搬出沙地,直接應用在具有 WSE 2.0 的安全、協作、團結的企業技術中。該遊戲的訊息處理結構如下面的圖 1 所示。

圖 1:Rock Paper Scissors 訊息處理和安全模型

Rock Paper Scissors 有兩個主要組件:一個是名為 RPSService 的 ASP.NET Web 服務,另一個是由多個使用者啟動並執行對等應用程式。RPSService 的作用是讓使用者註冊玩遊戲或尋找對手來玩遊戲。對等應用程式先是與 RPSService 通訊以找到要與之通訊的對方,然後在確定對手後直接與其對方進通訊。

對等:對於訊息處理,WSE 2.0 從基於傳統 HTTP 要求/響應(即 RPC 環境)轉換為採用可能同時具有對等訊息處理、非同步訊息處理和訊息佇列的環境。

Kerberos:整個應用程式是通過使用整合的 Windows Kerberos 支援建立的。使用 WSE 2.0,您可以用一種安全的方式串連網路。我們將進行驗證、數位簽章和加密訊息以確保具有最高的安全性,且這將完全基於 Windows 使用者帳戶。

便捷管理:不用編寫代碼來控制訪問,我們便可以通過策略設定檔來配置訊息的安全性。通過策略檔案,可以控制要實現的安全種類、要對訊息的哪部分進行數位簽章或加密及其實現方式,還可基於訊息時限性控制接受條件。目前,可以控制安全性的相應人員為:您的管理員。

Rock Paper Scissors:該應用程式的重要作用不在於應用程式本身,而是它與本例中不同實體通訊時使用安全訊息、策略和定址的方式。您猜不到,我正想象我的老闆說:“為了決定職員今年的獎金,我想讓你們每人運行一個小的應用程式 RockPaperScissors.exe...”

與 Windows 安全性整合的 Kerberos 令牌支援

我們要討論的 WSE 2.0 的第一部分是支援 Kerberos 安全性權杖。WSE 1.0 支援使用者名稱令牌和 X.509 安全性權杖。可以將這些令牌添加到安全性權杖的訊息集合,並用於建立數位簽章或執行加密。對於 WSE 2.0 來說,當在 Windows Server 2003 或帶有 Service Pack 1 的 Windows XP 上運行時,則已添加了 Kerberos 令牌支援。更重要的是,Kerberos 令牌支援能夠與整合的 Windows 安全性一起使用,這樣,不再需要將使用者名稱對應成 Windows 使用者,也不用另外設定使用者資料庫,可以基於 Windows 使用者控制對 Web 服務的訪問。

在為 RPSService 添加代碼之前,我要做的第一件事是在自己的項目中添加對 Microsoft.Web.Services 程式庫的引用。如果您的電腦上安裝的是 WSE 1.0,那麼添加引用時注意選擇 2.0 版的程式庫很重要。幸運的是,程式集的版本號碼就列在程式集名稱之後,因此可以輕鬆地選擇正確的程式集。圖 2 顯示的是選定了 WSE 2.0 程式庫的 Add Reference(添加引用)對話方塊。請注意,1.0 版本的程式庫就在選定的程式庫之前。

圖 2:將引用添加到 WSE 2.0 程式集

下面的代碼示範如何通過編程的方式將 Kerberos 令牌添加到令牌訊息集合。它是一方私下向另一方發送其動作時所使用的代碼。該代碼使用 WSE 2.0 的非同步 TCP 訊息功能(隨後將詳細說明),但用於添加令牌和加密的代碼類似於 WSE 1.0 中用於其他類型令牌的代碼。

using Microsoft.Web.Services.Security.Kerberos;   a€|KerberosToken peerToken;   a€|peerToken = new KerberosToken("host/" + OpponentUri.Host);   a€|envelope.Context.Security.Tokens.Add(peerToken);envelope.Context.Security.Elements.Add(new EncryptedData(peerToken));

請注意,令牌是通過傳遞串連主機的名稱建立的。用於建立該令牌的 Kerberos 標籤允許目前使用者與指示的主機進行通訊。具體來說,該令牌將用於加密要發送的訊息,以便只有該遠程主機才可以讀取這些訊息。

與其他類型令牌不同,Kerberos 令牌使用當前的 Windows 使用者安全上下文建立該令牌。如果您查詢已建立的令牌,您將會找到一個 Principal 成員屬性,它指示建立該令牌的使用者。我們從接收訊息(帶有 Kerberos 令牌)的代碼的主體中擷取使用者名稱。下面的 opponent 變數是一個 KerberosToken 對象,該對象是從傳入訊息的 Tokens 集合中獲得的。可以像下面擷取名稱那樣來擷取關於令牌建立者的資訊,但也可以調用 IsInRole() 方法來通過編程的方式確定 Active Directory 群組成員。

this.opposingNameLabel.Text     = "Playing: " + opponent.Principal.Identity.Name;

注意:如果在 Windows XP 上運行 Web 服務,則使用 Kerberos 令牌試圖串連到 Web 服務時,您可能會遇到以下錯誤:

Microsoft.Web.Services.Security.SecurityFault: An invalid security token was provided ---> System.Security.SecurityException: Unable to validate incoming Kerberos ST.  LsaLogonUser failed with the following message: A required privilege is not held by the client.  Substatus is 0.

出現該錯誤是由於調用名為 LogonUser 的安全 API 時,ASPNET 帳戶無法驗證 Kerberos 令牌。調用 LogonUser API 的使用者帳號要求具有“作為作業系統的一部分來操作”特權。在預設情況下,ASPNET 帳戶(即運行 ASP.NET 代碼的帳戶)不具有該特權。建議您在合適的伺服器平台如 Windows Server 2003 上運行已設定 Kerberos 安全的 Web 服務。在 Windows Server 2003 上,調用 LogonUser 時不需要“作為作業系統的一部分來操作”特權。在 Windows XP 上,可以使用 Local Security Policy 管理應用程式來配置擁有“作為作業系統的一部分來操作”特權的帳戶,包括 ASPNET 帳戶,但應該注意這會造成 ASP.NET 應用程式的安全性不夠嚴密。

安全性原則

雖然以上討論的代碼與 WSE 1.0 中的代碼非常相似,但它具有一個優點:將 Principal 對象與一個令牌關聯,可以用來尋找某個具體安全性權杖的特定屬性。這種方法存在的問題在於仍要編寫代碼來確定應屬於管理工作的訪問功能。為此,WSE 2.0 提供了建立策略檔案支援。

策略檔案基於 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 訊息來實現特定遊戲的通訊。一個人發送其動作後應用程式耐心的等待,直到對方玩家發送其動作。您可以將這看作類似於向倉庫發送發貨單,必須等待,直到有人手動封裝材料,才能發送一個指示請求完成的響應。

在上面顯示的 ReplyTo 代碼中,給出了建立 TCP 終結點需要的部分代碼。通過 SoapReceiver 類中的 Add 方法,可以註冊偵聽代碼。在本樣本中,我們建立了一個名為 PeerService 的類,它是偵聽傳入的 Rock Paper Scissors 遊戲的 SoapReceiver 類的子類。PeerService 類只是重載了處理傳入訊息的 Receive 方法。該類的代碼如下所示:

public class PeerService : SoapReceiver{    public static Form1 Form;    protected override void Receive(SoapEnvelope envelope)    {        Form.opponentPlay = (char)envelope.GetBodyObject(typeof(char));        foreach (SecurityToken tok in envelope.Context.Security.Tokens)        {if (tok is KerberosToken){    Form.opponent = (KerberosToken)tok;    break;}        }        Form.OpponentUri = envelope.Context.ReplyTo;        if (Form.peerToken == null)Form.peerToken     = new KerberosToken("host/"         + Form.OpponentUri.Host);        Form.opposingNameLabel.Invoke(new Form1.ReceivePlayDelegate(Form.ReceivePlay));    }}

Receive 方法採用 SoapEnvelope 對象作為參數。SoapEnvelope 類是從 XmlDocument 類派生得到的,這樣,您可以通過標準的 XML DOM 介面來訪問 SOAP 本文和標題。我們沒有使用 DOM 介面,而是利用 GetBodyObject 方法基於 SOAP 訊息本文中的 XML 來建立一個類,該方法在功能上使用了 XmlSerializer。我們將動作資訊儲存在 Form 類的一個公有屬性中。

我們還從請求中擷取 Kerberos 令牌並將它儲存。它將用於以後擷取對手的名稱。然後,儲存對手的 ReplyTo URI,以便我們瞭解接收響應的地址。我們亦可基於 URI 中顯示的主機先行建立 Kerberos 令牌,它將用於加密返回的訊息。

SoapReceivers 支援將偵聽傳入的串連,並在收到訊息時調用指示的類的 Receive 方法。進程的線程池中的某個線程將調用 Receive 方法,大多數情況下,該線程不是處理應用程式主視窗訊息泵的線程。因此,在 Receive 方法的末尾,我通過 Windows 表單中的一個控制項調用 Invoke 方法。這就啟動了主視窗線程中指定的委託功能,以使表單中各種控制項的常規互動正確進行。在本樣本中,委託確定兩次動作後的贏家並相應地更新使用者介面。

當調用 SoapReceivers.Add 方法(下面再次顯示了該方法)時,我們傳遞兩個參數:一個 URI 和偵聽類的類別類型。URI 指示了多項內容。首先,URI 類型為 soap.tcp。這表示它是一個通過 TCP 發送的 SOAP 訊息的 URI。URI 的主機名稱指示要偵聽的電腦,其後是用來偵聽傳入串連的 TCP 通訊埠號。在本樣本中,我們使用連接埠 3131。最好不要使用 1000 以下的連接埠號碼,因為它們是為特定類型的應用程式而保留的(例如,連接埠 80 用於 HTTP 伺服器)。

myPeerUri     = new Uri("soap.tcp://"       + System.Net.Dns.GetHostName()       + ":3131/RPSPeer1");SoapReceivers.Add(myPeerUri, typeof(PeerService));

向非同步 TCP 接聽程式發送訊息也同樣簡單。我們只要建立一個 SoapEnvelope 對象,並使用 SetBodyObject 方法將對象序列化到本文的 XML 中。SoapEnvelope 包含一個 Context 屬性,該屬性的使用類似於常規 HTTP 綁定的 SOAP 互動時使用的 SoapRequestContext 和 SoapResponseContext 屬性。我們用它來建立需要的 Action SOAP 標頭和可選的 ReplyTo 標題。我們還要添加前面建立的 Kerberos 令牌並用它來加密訊息。對於發送訊息,我們使用 SoapSender 類,該類與我們用於偵聽傳入訊息的 SoapReceiver 類相對應。SoapSender 類擷取其建構函式中的終結點 URI,然後將傳遞的 SoapEnvelope 發送到 Send 方法。發送對等訊息的代碼如下所示。

// Send MessageSoapEnvelope envelope = new SoapEnvelope();envelope.SetBodyObject(myPlay);envelope.Context.Action = new Action(OpponentUri.ToString());envelope.Context.Security.Tokens.Add(peerToken);envelope.Context.Security.Elements.Add(    new EncryptedData(peerToken));envelope.Context.ReplyTo = myPeerUri;SoapSender peerProxy = new SoapSender(this.OpponentUri);peerProxy.Send(envelope);

您可以從 Microsoft Download Center 擷取 Rock Paper Scissors 應用程式的完整原始碼(英文)。

WSE 2.0 的其他功能

通過 Rock Paper Scissors 應用程式,我們研究了 WSE 2.0 的許多功能,但是還有許多其他功能。使用者名稱令牌還可以與 Windows 安全性整合,如 Kerberos 令牌。由於支援安全上下文令牌,您可以建立有效對稱金鑰,用於對兩個終結點之間的多個訊息進行加密,而無需為每個訊息產生一個新的密鑰。除了安全上下文令牌以外,還支援建立安全性令牌服務 (Security Token Service),該服務為兩個終結點之間的通訊頒發上下文令牌。

對於訊息處理,我們僅討論了對發送非同步 TCP 訊息的支援,其實對同步請求/響應的支援也是同樣出色。該支援使用 SoapMethod 屬性,類似用於 .asmx Web 服務的 WebMethod 屬性,而且操作也相似。此外還支援在單獨的應用程式空間中調用服務,這似乎不是很好,但 Windows 訊息泵(建立窗式應用程式的基礎)同樣基於在單獨的應用程式空間中發送訊息。

WSE 2.0 更為迷人的地方之一是具有許多可擴充點。您可以做任何事情,包括從建立自己的自訂令牌處理常式到添加自己的策略支援。像 WSE 1.0 一樣,您仍然可以擴大處理範圍,但更重要的是如何在更高的層次上前進並利用已有的工作。

小結

在 MSDN 中,將會有更多的文章深入探討 WSE 2.0。我們將深入地討論策略、安全性、訊息處理和其他內容。希望 Rock Paper Scissors 為您展示了使用 WSE 2.0 開發的進階 Web 服務支援所具有的一些奇特新功能。同時希望它能像引發我們一樣引發您的想象力,在全新的環境中開發 Web 服務應用程式。




相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。