本文章是由機器翻譯。

宣告型應用程式

使用 WIF 進行宣告型授權

Michele Leroux Leroux

下載程式碼範例

過去幾年來,聯合安全性模型與宣告型存取控制越來越普及。 在聯盟的安全性模型驗證可執行由一個安全性權杖服務 (STS),並在 STS 可以發出安全性語彙基元帶有判斷提示已驗證的使用者和使用者 ’s 存取權限的身分識別宣告。 聯盟可讓使用者在他們自己網域進行驗證時被授與存取權應用程式和服務屬於另一個網域 — 前提網域必須具有之間建立的信任關係。 這種方法移除需要佈建和管理單一使用者的重複帳戶,並啟用單一登入 (SSO) 案例。 中央聯盟的安全性模型,讓應用程式和服務授權存取特色與功能根據來自受信任網域中的發行者 (STS) 宣告宣告為主的存取。 宣告可包含使用者、 角色或權限,相關資訊,而這對,非常有彈性的授權模型。 一起,聯盟的安全性和宣告式存取跨應用程式、 部門和更寬的生態系統的協力電腦啟用整合案例的範圍。

這個領域中的平台工具也有長足的進步。 Windows Identity Foundation (WIF) 是功能豐富的身分識別模型架構,專為建置宣告型應用程式與服務,以及支援主動和被動式聯合全性案例所設計。 與 WIF,可以啟用任何 ASP.NET 應用程式的被動聯盟,並整合到您的 ASP.NET 應用程式和 WCF 服務的宣告型授權模型而不會中斷一個 sweat。 此外,WIF 提供建置自訂的 STS 實作配管,並包含功能和控制項,以支援牽涉到受管理的資訊卡與身分識別選取器,例如 Windows CardSpace 驗證案例。

WIF 會大幅降低實作涉及聯盟和宣告式安全性的豐富的應用程式案例所需的程式碼。 此兩個部分文件中我著重在架構 ’s 核心功能用於啟用被動聯盟在 ASP.NET 應用程式中的和在 WCF 和 ASP.NET 支援宣告式安全性模型。 我專注於 WCF 此篇文章和 ASP.NET 中在稍後的圖案中。

為什麼聯盟和宣告式安全性?

聯盟和宣告式安全性的優點可以看到的幾個不同的目標內容中:

  • decoupling 驗證機制從應用程式和服務。
  • 以宣告取代角色,為更有彈性、 細微的成品的授權。
  • 降低與佈建和 deprovisioning 使用者相關的 IT 痛苦。
  • 授與信任包括可能是外部的聯盟協力廠商的網域存取應用程式功能和功能。

如果甚至其中一個這些目標響鈴則為 True,針對您的應用程式案例,採用一個宣告為主的模型,可以立即或最後會涉及聯盟的安全性是相當有用。

設計您的應用程式和服務時驗證和授權模型是這種設計的一部份。 比方說內部網路應用程式通常會預期雖然網際網路應用程式通常使用自訂認證存放區,如 Microsoft SQL Server 特定網域以他們的 Windows 認證進行驗證的使用者。 應用程式也可以要求憑證或智慧卡驗證或支援多種認證類型,使不同的使用者群組可以使用適當的型別。 如果您的應用程式將只 (和永遠) 預期單一的認證類型的驗證的使用者,您的工作就是很容易。 更經常個不,但是,由應用程式支援的認證類型可以逐步發展以支援的驗證的替代模式] 或 [容納一組不同的使用者的其他模式。

比方說應用程式可能會支援網域內防火牆後的內部使用者同時也支援在網際網路上的 [外部使用者。 當安全性模型的應用程式分離從驗證模式 — 如它可以使用宣告式模型 — 當您引入新模式的驗證是極少,如果有任何,影響到應用程式。

在類似 vein,應用程式都是更有彈性如果授權未繫結至一組固定角色。 如果您的應用程式永遠會依賴一組特定的角色來授權存取,而且這些角色會永遠執行方面的特性與功能的存取權限相同的意義,則您一次 ’re 很好的圖形中。 但是,所代表的意義角色通常而有所不同跨部門使用的應用程式,並因此需要自訂。 這可能表示評估以不同的方式取決於使用者 ’s 網域的角色,或讓自訂的角色,以建立來控制存取權限。 WIF 可採用簡單宣告式安全性模型,因此您可以提高從授權機制的角色 (如果適用的話)。 這種方式邏輯角色可以對應到更細微的一段宣告,及應用程式授權這些宣告為基礎的存取。 如果修改過或新角色值得一組不同的宣告是發給,isn’t 影響應用程式。

當然宣告可以是的不只是角色或權限。 使用宣告式模型新增的優點之一就是宣告可以等等攜帶的已驗證的使用者如電子郵件地址]、 [全名]、 [出生日期的相關資訊。 宣告也可用來驗證,例如資訊而不共用使用者 ’s 實際使用期限] 或 [出生日期 (許多使用者 don’t 要是公用的知識的資訊)。 宣告可能表示使用者是否至少是執行動作 (布林 (Boolean) 宣告指出 IsOver21 或 IsOver13),或請確認使用者屬於某特定部門而不共用的所有使用者所屬的部門清單所需的年齡。

雖然 decoupling 驗證機制和從應用程式和服務的特定角色方便,可調節變更,宣告為基礎的模型也是中央請授與存取屬於簡單多了任何受信任網域的使用者權限的聯盟的安全性案例的。 聯盟可以降低 IT 負荷量,以及部分的識別管理的相關風險。 它會移除需要維護跨多個應用程式或網域,使用者認證並這有助於減少風險佈建和 deprovisioning 跨網域的帳戶時 —,例如忘記刪除多個位置中的帳戶。 也密碼同步處理時管理帳戶的多份 aren’t 就會消失的問題。 聯盟也有助於 SSO 案例,因為使用者可以登入到一個應用程式,而且被授與存取權另 (可能是在安全性定義域) 而不需要再次進行驗證。 最後,新增新的信任關係的網域之間也進行簡單與聯盟的安全性平台,例如 Active Directory 聯盟伺服器 (ADFS) 和 WIF。 因此,擴充應用程式外部夥伴網域中公司的實體的其他網域或甚至被簡化。

作用中的聯盟與 WIF

使用中的聯盟案例以 「 WS-聯盟 Active 要求者設定檔為基礎 (請參閱 「 WS-聯盟 TC 功能在 oasis-open.org/committees/tc_home.php?wg_abbrev=wsfed ) 和 WS-Trust 規格 (請參閱在 docs.oasis-open.org/ws-sx/ws-trust/200512/ws-trust-1.3-os.html WS-Trust 1.3)。 從最高的層級 WS-Trust 說明四種服務作業的合約:發出、 驗證、 更新和 [取消]。 分別,這些作業是由用戶端呼叫以要求以驗證更新過期的安全性語彙基元,並取消應該不再使用的安全性權杖一個安全性權杖的安全性憑證。 每個作業處理一個要求的形式的訊息的安全性語彙基元 (RST),並將回應傳送在表單中的一個 RST 回應 (RSTR) 後面 WS-Trust 規格。 這些 WS-Trust 功能由 STS 實作 (或語彙基元發行者),重要的參與者在任何聯盟的安全性案例中。

圖 1 說明了簡單的使用中聯盟案例。 這種情況下會涉及到 Windows 用戶端應用程式 (要求者)、 WCF 服務 (依賴廠商或 RP),以及 STS 屬於 RP 網域 (RP STS)。 如圖所示用戶端會使用 WCF Proxy 來協調第一個驗證以 RP-STS 然後要求安全性語彙基元,然後呼叫 [RP 傳遞已發行的安全性語彙基元,連同要求。


圖 1 A 簡易 Active 聯盟案例

在這種情況下 RP STS 也是識別提供者 (IdP) 進行使用者驗證到 RP 網域。 表示 RP STS 負責驗證使用者、 判斷提示這些使用者的身分識別及發出授權相關 [RP 的宣告。 RP 驗證安全性語彙基元由 RP STS 所發出授權發行宣告為基礎的存取。

我建立 Todo 清單應用程式,以促進此案例的實作討論區。 伴隨的程式碼範例包含 WPF 用戶端]、 [WCF 服務] 和 [作用中 STS 以 WIF 實作。 若要提供進一步的 WCF] 服務的內容 TodoListService,實作 ITodoListService 合約 的 圖 2 所示。 用戶端會呼叫服務,藉由使用 WCF Proxy 取得所有 Todo 項目,並以新增、 更新或刪除項目。 TodoListService 依賴建立、 讀取、 更新及刪除來授權存取其作業的宣告。

圖 2 的 ITodoListService 定義

[ServiceContract(Namespace="urn:TodoListApp/2009/06")]
public interface ITodoListService
{
    [OperationContract]
    List<TodoItem> GetItems();
    [OperationContract]
    string CreateItem(TodoItem item);
    [OperationContract]
    void UpdateItem(TodoItem item);
    [OperationContract]
    void DeleteItem(string id);
}

若要實作此作用中的聯盟案例,您需要請依照下列四個步驟執行:

  1. 對於 [TodoListService 公開聯盟的安全性 WCF 端點。
  2. 產生 WCF Proxy 用戶端應用程式,並初始化驗證 RP STS 以認證 Proxy。
  3. 啟用以啟用宣告型授權 TodoListService 的 WIF。
  4. 將權限要求 (IsInRole) 或其他授權檢查,來控制可存取的服務作業或其他功能。

我討論這些步驟,請依照下列各節。

公開聯盟端點

宣告式 WCF 服務通常會公開發出例如那些根據標準 SAML 語彙基元 (Token) 收到的聯盟結束點。 WCF 提供支援聯盟的安全性情況與 WS-信任的兩個繫結。 WSFederationHttpBinding 是根據 WS-Trust 2005 (較早版本的通訊協定),原始標準繫結,且 WS2007FederationHttpBinding 為最新版本的繫結 (釋放與 Microsoft.NET Framework 3.5),且支援 WS-Trust 1.3 核准的標準。 通常,您應該使用 WS2007FederationHttpBinding 除非交互操作性需求規定較早版本的使用。 STS 根據 ADFS 第 2 版或 WIF 可以支援任一版本的 「 WS-信任。

當您公開為服務的聯盟的端點時,通常會提供預期的安全性語彙基元格式、 必要和選擇性的宣告型別和受信任的語彙基元發行者的資訊。 圖 3 顯示列出透過 WS2007FederationHttpBinding 公開單一的聯盟的端點的 TodoListService system.serviceModel。

圖 3 的 [TodoListService 公開的聯盟的端點

<system.serviceModel>
  <services>
    <service name="TodoList.TodoListService" 
behaviorConfiguration="serviceBehavior">
      <endpoint address="" binding="ws2007FederationHttpBinding" bindingConfiguration="wsFed" contract="Contracts.ITodoListService" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8000/TodoListService"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <bindings>
    <ws2007FederationHttpBinding>
      <binding name="wsFed">
        <security mode="Message" issuedTokenType=
“http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-.1#SAMLV1.1" issuedKeyType="SymmetricKey" negotiateServiceCredential="true">
          <message>
            <claimTypeRequirements>
              <add claimType= 
“https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="false"/>
              <add claimType= "urn:TodoListApp/2009/06/claims/permission" 
isOptional="false"/>
            </claimTypeRequirements>
            <issuerMetadata address="http://localhost:8010/rpsts/mex" />
          </message>
        </security>
      </binding>
    </ws2007FederationHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="serviceBehavior">
        <serviceMetadata/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

雖然這不是嚴格的需求聯盟的安全性情況通常依賴 SAML 語彙基元。 這個案例的 SAML 1.1 語彙基元 (Token) 用,所指定的 issuedTokenType URI ( docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0.pdf )。 替代的語彙基元類型時,例如 SAML 1.0 或 SAML 2.0 使用該標準的 URI。  當然聯盟繫結組態中所指出的 STS 必須支援您要求的語彙基元型別。

[訊息] 區段中的其他相關設定包括 issuedKeyType 和 negotiateServiceCredential。 [issuedKeyType] 設定指出證明金鑰 (請參閱 blogs.msdn.com/vbertocci/archive/2008/01/02/on-prooftokens.aspx ) 是對稱式 (預設值) 或非對稱式 (執行更多的額外負荷)。 再一次此設定必須與 [STS 相容。 如果 negotiateServiceCredential 是設為 true 用戶端 doesn’t 需要存取公用 RP 鍵一 priori 但交涉並不是可互通的通訊協定。 如果用戶端不是 WCF 用戶端,應該將 negotiateServiceCredential 設為 false。 不過別擔心! 如果設定為 false,Proxy 產生與 SvcUtil 提供 RP ’s 公開金鑰 base64 編碼複本與用戶端。

claimTypeRequirements 一節中所提供的宣告型別表示必要和選擇性聲稱服務依賴授權的型別。 在這種情況下,服務所預期來識別使用者和至少一個使用權限的名稱宣告聲稱 — 自訂宣告型別,指出使用者 ’s 權限,以建立、 讀取、 更新或刪除 Todo 項目。 (這些宣告型別詳列稍後於 的 圖 4)。宣告型別清單包含在服務中繼資料,因此可用戶端就可以將此資訊包含在 [RST。 經常,[STS 知道它會發出這表示清單 doesn’t 必須要徹底聯盟繫結中豬最喜歡一個特定 RP 的宣告。

圖 4 Claims 發給每 Todo 清單應用程式案例的使用者

這種情況下信任的語彙基元發行者是 RP-STS 這種 WIF 用來實作。 RP STS 會公開單一的 WS-Trust 端點 http://localhost:8010/rpsts,在它的中繼資料交換位址處,則 http://localhost:8010/rpsts/mex。 如此當用戶端產生 Proxy,可以找出可用的 STS 端點 的 圖 3,發行者 ’s 中繼資料位址是在 issuerMetadata 區段中提供。

假設在 STS 已公開多個端點 — 為範例驗證使用 Windows 認證 http://localhost:8010/rpsts/internal 在內部網路使用者,並驗證網際網路使用者以使用者名稱和密碼在 http://localhost:8010/rpsts/external。 RP 服務可以選擇性地指定特定的發行者端點,以便與 [STS 通訊組態時用戶端產生 Proxy,符合第一個相容的端點代替該端點相關聯其聯盟的端點組態。 您完成提供 issuerMetadata 和發行者元素的位址,如下所示:

<issuerMetadata address="http://localhost:8010/rpsts/mex" />
<issuer address="http://localhost:8010/rpsts/mex/external" />

這種方法的優點是簡化的用戶端 Proxy 產生,如果有多個可從中選擇的 STS 端點,並且 [RP 想要使用哪一種會影響。 如果 [RP doesn’t 處理用戶端驗證到哪些端點,最好提供 issuerMetadata 設定,並讓用戶端應用程式判斷適當的端點來進行驗證。

請記住: 如果服務組態會省略 issuerMetadata 項目,並提供給發行者地址,地址應該評估為發行者 ’s 其中一定是不可能對應到實體的 STS 端點位址的邏輯 URI (http://localhost:8010/rpsts/issuer)。 一個對等的設定,在用戶端會提示使用者從相同的發行者 (透過 Windows CardSpace) 中選取受管理的資訊卡片和智慧卡也必須符合要求的語彙基元格式準則並聲稱型別。 在使用中的聯盟的案例,Windows CardSpace 更多資訊,請參閱 wpfandcardspace.codeplex.com

用戶端 Proxy 產生

當您產生使用 SvcUtil 或加入服務參考的 Windows 用戶端 Proxy 時,發行者中繼資料交換位址用來收集公開的發行者端點的相關資訊。 若要重複,一些可能的案例是:

  • 如果繫結的發行者中繼資料位址沒有特定的發行者位址 RP 服務的端點補給聯盟,用戶端組態將會包含第一個的通訊協定相容 STS 結束點與任何其他相容的端點註解若要選擇性地使用用戶端開發人員。
  • 如果 RP 服務聯盟的繫結提供發行者中繼資料位址和特定的發行者位址,用戶端組態將會包含該特定的地址 (假設它相容的通訊協定)。
  • 如果 RP 服務聯盟的繫結提供僅中繼資料位址,用戶端組態將會包含僅中繼資料位址同時也沒有繫結組態為發行者。 這表示識別選取器等將觸發 CardSpace,如先前所述。

假設用戶端會產生為其設定顯示於 [圖 3 TodoListService Proxy,而且在 STS 會公開單一端點,WS2007FederationHttpBinding 組態的用戶端版本會包含下列的發行者及 issuerMetadata 設定:

<issuer address="http://localhost:8010/rpsts" 
        binding="ws2007HttpBinding" 
        bindingConfiguration="http://localhost:8010/rpsts">
  <identity>
    <certificate encodedValue="[base64 encoded RP-STS certificate]" />
  </identity>
</issuer>
<issuerMetadata address="http://localhost:8010/rpsts/mex" />

請注意發照者項目指定發行者端點和必要的繫結設定與該端點進行通訊。 在這種情況下用戶端驗證要以使用者名稱和密碼使用郵件安全性 STS 中是下列 WS2007HttpBinding 組態中所示:

<ws2007HttpBinding>
    <binding name="http://localhost:8010/rpsts" >
        <security mode="Message">
            <message clientCredentialType="UserName" 
                     negotiateServiceCredential="false" 
                     algorithmSuite="Default" 
                     establishSecurityContext="false" />
        </security>
    </binding>
</ws2007HttpBinding>

用戶端端點會將聯盟繫結組態與 RP 端點產生關聯:

<client>
  <endpoint address="http://localhost:8000/TodoListService" 
            binding="ws2007FederationHttpBinding" 
            bindingConfiguration="wsFed"
            contract="TodoList.ITodoListService" name="default">
    <identity>
      <certificate encodedValue="[base64 encoded RP certificate" />
    </identity>
  </endpoint>
</client>

以這個設定用戶端 Proxy 必須只之前先初始化具有有效的使用者名稱和密碼呼叫服務:

TodoListServiceProxy _Proxy = new TodoListServiceProxy("default");

if (!ShowLogin()) return;

this._Proxy.ClientCredentials.UserName.UserName = this.Username;
this._Proxy.ClientCredentials.UserName.Password = this.Password;
this._TodoItems = this._Proxy.GetItems();

語彙基元發佈

在 Proxy 先提供認證來驗證 RP-STS,傳送 RST 詢問 SAML 1.1 語彙基元指出 [RP 需要至少一個名稱和使用權限的宣告。 使用者驗證對 STS 認證存放區,並適當宣告所發出的已驗證的使用者。 在 Proxy 再處理 RSTR,攜帶發行的權杖,並將該語彙基元 (Token) 傳遞給 RP 來建立安全的工作階段,為已驗證的使用者。

為使本範例在 STS 與 WIF 而建立,且驗證對自訂認證存放區的使用者發出 的 圖 4 根據每位使用者的宣告。

STS 根據 ADFS 第 2 版的附註會驗證使用者對 Windows 網域,並發行根據 ADFS 組態來宣告。 WIF 為基礎的自訂 STS 可以驗證使用者對您所選擇的認證存放區,但您必須復原您自己的程式碼,以管理認證存放區和相關的宣告對應程序。

 識別模型組態

若要以便宣告型授權您使用 WIF 的 WCF 服務的初始化聯盟 ServiceHost 執行個體。 您可以執行這項動作以程式設計的方式呼叫 ConfigureServiceHost 方法 FederatedServiceCredentials] 型別所公開的如下所示:

ServiceHost host = new ServiceHost(typeof(TodoList.TodoListService));
FederatedServiceCredentials.ConfigureServiceHost(host);
host.Open();

您可以使用行為延伸 ConfigurationServiceHostBehaviorExtension 以宣告方式達成相同的結果:

<serviceBehaviors>
  <behavior name="fedBehavior" > 
    <federatedServiceHostConfiguration/>
    <serviceMetadata />
  </behavior>
</serviceBehaviors>

不論是哪一種 [ServiceHost 已指派給該服務的磁碟機宣告型授權行為的 FederatedServiceCredentials 型別的執行個體。 以程式設計的方式或 microsoft.identityModel 組態區段,為服務,可以進行初始化這個型別。 身份識別模型設定 WIF 特有,並提供宣告型授權 ASP.NET 和 WCF 應用程式中,最其中摘要於 的 圖 5 的設定。

圖 5 的 基本 microsoft.identityModel 項目摘要

對於使用 WIF 的 WCF 服務,您不再需要初始化 ServiceHost 與典型的 WCF 驗證和授權行為。 WIF 取代了這,並提供更簡潔的方法的一般設定安全性。 (WIF 是有用之外宣告式和聯盟案例)。 圖 6 顯示識別所用的 「 TodoListService 的模型設定。

圖 6 的 常提供給 WCF 服務的身分識別模型設定

<microsoft.identityModel>
  <service>
    <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.
      ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, 
      Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <trustedIssuers>
        <add name="http://localhost:8010/rpsts" thumbprint=
"c3 95 cd 4a 74 09 a7 77 d4 e3 de 46 d7 08 49 86 76 1a 99 50"/>
      </trustedIssuers>
    </issuerNameRegistry>
    <serviceCertificate>
      <certificateReference findValue="CN=RP" storeLocation="LocalMachine" 
         storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
    </serviceCertificate>
    <audienceUris mode="Always">
      <add value="http://localhost:8000/TodoService"/>
    </audienceUris>
    <certificateValidation certificateValidationMode="PeerTrust" />         
    <securityTokenHandlers>
      <remove type="Microsoft.IdentityModel.Tokens.Saml11.
         Saml11SecurityTokenHandler, Microsoft.IdentityModel, 
         Version=1.0.0.0, Culture=neutral, 
         PublicKeyToken=31bf3856ad364e35"/>
      <add type="Microsoft.IdentityModel.Tokens.Saml11.
         Saml11SecurityTokenHandler, Microsoft.IdentityModel, 
         Version=1.0.0.0, Culture=neutral, 
         PublicKeyToken=31bf3856ad364e35">
        <samlSecurityTokenRequirement >
          <roleClaimType 
            value="urn:TodoListApp/2009/06/claims/permission"/>
        </samlSecurityTokenRequirement>
      </add>
    </securityTokenHandlers>
    <claimsAuthorizationManager 
      type="TodoList.CustomClaimsAuthorizationManager, TodoList"/>
  </service>
</microsoft.identityModel>

issuerNameRegistry 設定用來指定任何受信任的憑證簽發者。 如果您使用 [ConfigurationBasedIssuerNameRegistry 的 圖 6 所示您必須藉由指定其 thumbprints 提供受信任的憑證簽發者的清單。 在執行階段 [ConfigurationBasedIssuerNameRegistry 會檢查 X509 安全性語彙基元對這份清單,並拒絕那些具 thumbprints 在清單中找不到。 您可以使用 [SimpleIssuerNameRegistry 以允許任何 X509 或 RSA 語彙基元,但更有可能您會提供自訂的 IssuerNameRegistry 型別來驗證使用您自己的啟發式 (如果 [ConfigurationBasedIssuerNameRegistry doesn’t 做可行的語彙基元 (Token)。

圖 6 中組態會拒絕未簽署 RP STS 由任何語彙基元 (使用憑證指紋的 CN = RPSTS)。 下列的設定而是指定自訂的 IssuerNameRegistry 類型,TrustedIssuerNameRegistry:

<issuerNameRegistry type="TodoListHost.TrustedIssuerNameRegistry, TodoListHost"/>

TrustedIssuerNameRegistry 實作用來達到相同的結果 — 拒絕語彙基元 (Token) 未簽署的 CN = RPSTS 藉由檢查連入的語彙基元的主旨名稱:

public class TrustedIssuerNameRegistry : IssuerNameRegistry
{
    public override string GetIssuerName(SecurityToken securityToken)
    {
        X509SecurityToken x509Token = securityToken as
            X509SecurityToken;
        if (x509Token != null)
        {
            if (String.Equals(x509Token.Certificate.SubjectName.Name,
                "CN=RPSTS"))
            {
                return x509Token.Certificate.SubjectName.Name;
            }
        }

        throw new SecurityTokenException("Untrusted issuer.");
    }
}

圖 6 的 [serviceCertificate] 設定指示假設所發行的 STS 加密以 [RP 憑證,以用來解密連入安全性語彙基元。 Todo 清單] 應用程式,RP STS 加密為的 RP CN 使用公開金鑰的語彙基元 (Token) = RP。

通常,SAML 語彙基元 (Token) 包括評估為 [RP 指出誰語彙基元,針對所發出的觀眾 URI 項目。 您可以明確拒絕不預定要傳送至 [RP 語彙基元。 預設情況下,audienceUris 模式已設定為 [永遠這表示您必須提供至少一個 URI 為針對連入的語彙基元 (Token) 的驗證。 的 圖 6,在組態可讓包括對象符合 TodoListService 位址 URI 的 SAML 權杖。 雖然通常不建議您可以設定 audienceUris 模式為 [永遠不檢查抑制連入的 SAML 語彙基元觀眾限制條件的評估:

<audienceUris mode="Never"/>

注意當用戶端傳送一個 RST 至 [STS,它通常包含表示語彙基元應該發出到一個 AppliesTo 設定 — [RP。 在 STS 可以使用這項資訊來填入 SAML 語彙基元的對象的 URI。

設定控制如何傳入 509 語彙基元 (Token) X certificateValidation — 例如用於權杖簽章的那些 — 會進行驗證。 的 圖 6,在 certificateValidationMode 設為表示找到相關聯的憑證才會有效憑證的 PeerTrust TrustedPeople 存放區中。 這項設定會比 PeerOrChainTrust (預設值) 的語彙基元發行者驗證更適合,因為它需要您明確地安裝憑證存放區中的 [受信任的憑證。 PeerOrChainTrust 指示是否根憑證授權單位 (CA) 是受信任,也授權簽章其中大部分的機器上包括重大的受信任的 CA 清單。

我很快就討論幾個 圖 6圖 5 和其他設定。 使 WIF 初始化主題相關的其他一個點就是可以也以程式設計方式初始化 FederatedServiceCredentials 的執行個體而將它傳遞給 ConfigureServiceHost,而不是從 microsoft.identityModel 區段初始化。 下列程式碼可說明這點:

ServiceHost host = new ServiceHost(typeof(TodoList.TodoListService));

ServiceConfiguration fedConfig = new ServiceConfiguration();
fedConfig.IssuerNameRegistry = new TrustedIssuerNameRegistry();
fedConfig.AudienceRestriction.AudienceMode = AudienceUriMode.Always;
fedConfig.AudienceRestriction.AllowedAudienceUris.Add(new 
Uri("http://localhost:8000/TodoListService"));
fedConfig.CertificateValidationMode = 
X509CertificateValidationMode.PeerTrust;
fedConfig.ServiceCertificate = CertificateUtil.GetCertificate(
StoreName.My, StoreLocation.LocalMachine, "CN=RP");

FederatedServiceCredentials fedCreds = 
new FederatedServiceCredentials(fedConfig);

FederatedServiceCredentials.ConfigureServiceHost(host,fedConfig);
host.Open();

以程式設計方式初始化時特別有用初始化 ServiceHost 從套用至整個伺服器陣列的資料庫設定。

WIF 元件架構

當您套用 WIF 行為至一個 ServiceHost 時,將幾個 WIF 元件初始化為促進宣告型授權 — 它們的 WCF 擴充功能的許多。 最終,這會導致 ClaimsPrincipal,附加到要求的執行緒,而且這支援宣告型授權。 圖 7 擷取核心 WIF 元件和 [ServiceHost 之間的關係。


圖 7 的 WIF 與已安裝的核心元件

FederatedServiceCredentials 型別會取代預設 ServiceCredentials 行為並 IdentityModelServiceAuthorizationManager (FederatedServiceCredentials 初始化期間安裝) 來取代預設值 ServiceAuthorizationBehavior。 FederatedServiceCredentials 也會建構一個 FederatedSecurityTokenManager 執行個體。  集體,驗證和授權針對每個要求的 [ClaimsAuthenticationManager、 [ClaimsAuthorizationManager 和套用至特定的要求的 SecurityTokenHandler 協助磁碟機這些型別。

圖 8 的這些元件通往建構要求執行緒的安全性主體的通訊流程說明 — 在這種情況下一個 ClaimsPrincipal 鍵入 — 並授權存取這個安全性原則為基礎的機會。


圖 8 的 那建立並可依據 [ClaimsPrincipal 授權的元件

FederatedSecurityTokenManager 傳回適當的語彙基元處理常式為要求 — 這在此情況下會是 [Saml11SecurityTokenHandler — 提供 [ClaimsAuthorizationManager 的參考。 語彙基元的處理常式建構從連入的語彙基元 ClaimsIdentity、 建立 ClaimsPrincipal (透過包裝函式類別),並將其傳遞至 ValidateToken 方法為 [ClaimsAuthorizationManager。 這會產生有機會修改或取代會附加至要求執行緒的 ClaimsPrincipal。 預設實作只會傳回所提供的相同 ClaimsPrincipal:

public virtual IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
    return incomingPrincipal;
}

您可以考慮提供自訂 ClaimsAuthenticationManager,將連入宣告從安全性語彙基元轉換成 [RP 可用來授權存取的項目。 為使本範例不過,SAML 語彙基元執行適當的 RP 宣告 RP-STS 所發出,因此從那些宣告建構 ClaimsPrincipal 適用的授權。

接下來,在參考 [ClaimsAuthorizationManager 的 IdentityModelServiceAuthorizationManager 呼叫其 CheckAccess] 方法產生自訂如何控制存取的機會。 預設實作不會限制存取:

public virtual bool CheckAccess(AuthorizationContext context)
{
    return true;
}

AuthorizationContext 參數提供存取 [ClaimsPrincipal 和其相關聯的宣告、 動作 (例如在 URI 指出服務作業所要呼叫) 要求的相關集合和要求 (比方說服務 URI),這會很有用明確執行通過相同的授權路徑的多個服務的呼叫與相關資源的相關資訊。 若要實作集中式的授權,您可以提供自訂 ClaimsAuthorizationManager。 當我將討論授權的技巧,我將說明一個範例。

在.NET Framework 以角色為基礎的安全性成立上前提 IPrincipal 為基礎的安全性主體已附加到每個執行緒,且這個安全性原則在 IIdentity 實作包裝已驗證使用者的識別。 沒有 WIF,WCF 會將安全性主體附加至根據 system.serviceModel 組態進行驗證及授權每個要求執行緒。 根據所呈現的驗證認證的型別建構的 IIdentity 型別時。 例如 Windows 認證會評估為一個 WindowsIdentity 到一個 X509Identity X.509 憑證] 和 [到一個 GenericIdentity 一個使用者名稱權杖。 ServiceAuthorizationBehavior 控制 IPrincipal 包裝函式來識別的類型。 比方說與 Windows 授權建構一個 WindowsPrincipal ; 與 ASP.NET 成員資格提供者,一個 RoleProviderPrincipal。 否則,自訂授權原則用來建構您所選擇的 IPrincipal 物件。 IPrincipal 物件公開的 IsInRole 方法時,可以呼叫直接或間接透過控制對特色與功能的存取權限要求。

WIF 藉由提供 ClaimsPrincipal 和 ClaimsIdentity 型別來擴充這個模型 — 根據 IClaimsPrincipal 和 IClaimsIdentity —,最後是衍生自 IPrincipal 和 IIdentity。 所有的語彙基元 (Token) 會對應到與 WIF ClaimsIdentity。 驗證每個連入的安全性語彙基元時其相關聯的 SecurityTokenHandler 型別建構一個 ClaimsIdentity 提供適當的宣告。 (萬一語彙基元會產生多個 ClaimsIdentity 執行個體),包裝這個 ClaimsIdentity 中一個 ClaimsIdentityCollection,這個集合會被包裝在一個 ClaimsPrincipal 並附加到要求的執行緒。 它是這個 ClaimsPrincipal 是 WCF 服務的 WIF 授權的核心。

宣告型授權

WCF 服務的授權的方法將會很可能涉及下列技術之一:

  • 使用 [ClaimsPrincipal 執行動態 IsInRole 檢查。
  • 使用 PrincipalPermission 型別來執行動態的權限要求。
  • 使用 [PrincipalPermissionAttribute 以提供在每個作業的宣告式的權限要求。
  • 提供自訂 ClaimsAuthorizationManager 到集中在單一元件中的存取檢查。

這些選項的前三個最終會依賴 ClaimsPrincipal 型別所公開的 IsInRole 方法。 這完全 doesn’t 表示您正在進行以角色為基礎的安全性 ; 它只是表示您選取角色宣告型別,以便正確宣告核對要求傳遞至 IsInRole 的宣告。 最 schemas.microsoft.com/ws/2008/06/identity/claims/role WIF 預設角色的宣告型別。 如果與聯盟案例問題相關的 [STS 這種類型的主張,您可以選擇性地控制存取根據此宣告型別。 Todo 清單應用程式分析藍本我提到以便識別模型組態必須指定這為角色宣告型別,以促進 IsInRole 檢查的自訂使用權限的宣告類型用於授權。

您為預期的語彙基元型別,在這個情況將 Saml11SecurityTokenHandler 提供 [SecurityTokenHandler 的角色的宣告類型。 如 的 圖 6 所說明您可以將一個 SecurityTokenHandler 預設的組態修改藉由將它移除,然後再次,新增相同的一個指定慣用的屬性設定值。 SAML 語彙基元的處理常式都有一個 samlSecurityTokenRequirement 區段,在其中您可以提供名稱的設定或角色主張沿著具有憑證驗證和 Windows 語彙基元 (Token) 和相關的其他設定等型別。 此劇情我提供自訂的角色的宣告類型:

<samlSecurityTokenRequirement >
  <roleClaimType value= "urn:TodoListApp/2009/06/claims/permission"/>
</samlSecurityTokenRequirement>

這表示是,IsInRole 都會呼叫 [ClaimsPrincipal 我檢查的有效使用權限宣告任何時間。 一個方法若要完成這個程序是明確地呼叫 IsInRole 前一段程式碼執行,需要特定的宣告。 您可以透過 Thread.CurrentPrincipal 屬性存取目前的主體,如下所示:

if (!Thread.CurrentPrincipal.
IsInRole("urn:TodoListApp/2009/06/claims/permission/delete"))
  throw new SecurityException("Access is denied.");

除了從執行階段明確 IsInRole 檢查,您也可以撰寫使用 PrincipalPermission 類型的傳統以角色為基礎的權限要求。 初始化型別與必要的角色主張 (第二個建構函式參數),並呼叫 Demand 時呼叫 IsInRole 方法的目前主體。 如果找不到宣告,則會擲回例外狀況:

PrincipalPermission p = new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/delete");
p.Demand();

您也可以建置來收集要檢查的幾個宣告 PermissionSet:

PermissionSet ps = new PermissionSet(PermissionState.Unrestricted);
ps.AddPermission(new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/create"));
ps.AddPermission(new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/read"));
ps.Demand();

如果存取檢查套用到整個服務作業,您可以套用 [PrincipalPermissionAttribute 改,這是不錯的方法以宣告方式建立關聯到被呼叫作業的必要的宣告。 這些屬性也可以是堆疊來檢查有多個宣告的:

[PrincipalPermission(SecurityAction.Demand, Role = Constants.Permissions.Create)]
[PrincipalPermission(SecurityAction.Demand, Role = Constants.Permissions.Read)]
public string CreateItem(TodoItem item)

在某些情況下您可能會有用來集中管理的授權,這表示會提供自訂 ClaimsAuthorizationManager 執行存取檢查的單一元件。 圖 6 說明如何設定自訂 ClaimsAuthorizationManager,並為 [TodoListService 這個實作所示 圖 9 (部分列出為了保持簡潔)。

圖 9 的 自訂 ClaimsAuthorizationManager 實作

class CustomClaimsAuthorizationManager : ClaimsAuthorizationManager
{
    public CustomClaimsAuthorizationManager()
    {
    }

    public override bool CheckAccess(AuthorizationContext context)
    {
        
        if (context.Resource.Where(x=> x.ClaimType == 
            System.IdentityModel.Claims.ClaimTypes.Name && x.Value == 
            "http://localhost:8000/TodoListService").Count() > 0)
        {
            if (context.Action.Where(x=> x.ClaimType == 
                System.IdentityModel.Claims.ClaimTypes.Name && x.Value == 
                Constants.Actions.GetItems).Count() > 0)
            {
                return
                    context.Principal.IsInRole(
                       Constants.Permissions.Read);
            }

        // other action checks for TodoListService
        }
        return false;
    }  
}

ClaimsAuthorizationManager CheckAccess 接收參考至 (在此情況下,服務 URI) 的資源為 AuthorizationContext 參數 ; 動作 (在此情況,指出服務作業 URI 的單一動作); 集合並在還不附加至要求執行緒的 ClaimsPrincipal 提供覆寫。 您可以檢查資源如果元件跨服務,共用與這個範例不會進行說明。 主要,您將檢查服務作業 URI 的核對清單動作,並且執行 IsInRole 檢查根據要操作的需求。

通常,我 ’m 不大風扇的 decoupling 授權檢查,從受保護的作業或程式碼區塊。 它會更容易維護在活動的內容中的一個位置宣告的程式碼。

若要繼續

此時您應該有相當好如何設定使用中的聯盟案例中,以 WCF 和包括瞭解 WCF 和 Proxy 產生語意 ; 語彙基元發佈程序 ; 設定 WIF AT 服務 ; 和實作各種不同的宣告型授權技術的聯盟繫結的 WIF。 待處理的文件中, 我將繼續進行與 ASP.NET 和 WIF 被動聯盟。

Michele Leroux Bustamante 是主要的架構設計人員在 IDesign Microsoft 地區導演聖地牙哥和針對已連線的系統的 Microsoft MVP。 她最新的活頁簿是 「 學習 WCF 」。您可以透過 mlb@idesign.net 與她連絡,或請造訪 idesign.net。 她也在 dasblonde.net 的部落格。