如何:使用 WIF 和 ACS 在宣告感知 ASP.NET 應用程式中實作宣告授權

更新日期:2015 年 6 月 19 日

適用對象:Azure

套用至

  • Microsoft® Azure™ 存取控制服務 (ACS)

  • Windows® Identity Foundation (WIF)

  • ASP.NET

總結

本主題描述如何使用 WIF 和 ACS 在宣告感知 ASP.NET Web 應用程式中實作宣告型存取控制 (CBAC) 授權。

目錄

  • 目標

  • 概觀

  • 步驟摘要

  • 步驟 1 – 實作一個宣告授權庫

  • 步驟 2 – 設定 ASP.NET 應用程式,以使用宣告授權庫

  • 步驟 3 – 設定授權原則

  • 相關項目:

目標

  • 從應用程式外部化授權邏輯。

  • 實作除了角色以外的授權檢查可以更精細地控制授權。

  • 提供給以原則為導向的宣告式授權管理。

概觀

宣告授權以使用權杖內攜帶的資訊 (宣告) 為基礎。 當僅根據角色仍不足以做出授權決定時,使用宣告授權很有用。 例如,在財務應用程式中,可以根據任職期間與其他屬性,給予相同角色在帳戶間轉帳的不同限制。 這類屬性的形式可以是跟隨角色而來的宣告,因此可以讓系統做出更精細的授權決定。

步驟摘要

  • 步驟 1 – 實作一個宣告授權庫

  • 步驟 2 – 設定 ASP.NET 應用程式,以使用宣告授權庫

  • 步驟 3 – 設定授權原則

步驟 1 – 實作一個宣告授權庫

此步驟說明如何建立一個外部類別庫,以讀取來自設定檔的存取原則,並強制實施存取檢查。 以下範例說明如何實作宣告授權庫,以根據郵遞區號宣告做出授權決定。

實作宣告授權庫

  1. 確定您正在以系統管理員模式執行 Visual Studio®。

  2. 在 [方案總管] 中您想要的方案上按一下滑鼠右鍵,新增 [類別庫] 專案,然後為它命名,例如 MyClaimsAuthorizationManager。

  3. 刪除預設類別 Class1.cs

  4. 新增一個新類別並為它命名,例如 ZipClaimsAuthorizationManager。 如此就會根據郵遞區號實作授權。

  5. 新增 Microsoft.IdentityModelSystem.Web 組件的參考。

  6. 新增下列宣告。

    using System.IO;
    using System.Xml; 
    using Microsoft.IdentityModel.Claims; 
    using Microsoft.IdentityModel.Configuration; 
    
  7. 展開 ClaimsAuthorizationManager 類別,覆寫它的 AccessCheck 方法,然後對您的 ZipClaimsAuthorizationManager 類別實作建構函式。 您的程式碼看起來應該像下面這樣。

    namespace MyClaimsAuthorizationManager 
    { 
        class ZipClaimsAuthorizationManager : ClaimsAuthorizationManager 
        { 
            private static Dictionary<string, int> m_policies = new Dictionary<string, int>(); 
    
            public ZipClaimsAuthorizationManager(object config) 
            { 
                XmlNodeList nodes = config as XmlNodeList; 
                foreach (XmlNode node in nodes) 
                { 
                    { 
                        //FIND ZIP CLAIM IN THE POLICY IN WEB.CONFIG AND GET ITS VALUE 
                        //ADD THE VALUE TO MODULE SCOPE m_policies 
                        XmlTextReader reader = new XmlTextReader(new StringReader(node.OuterXml)); 
                        reader.MoveToContent(); 
                        string resource = reader.GetAttribute("resource"); 
                        reader.Read(); 
                        string claimType = reader.GetAttribute("claimType"); 
                        if (claimType.CompareTo(ClaimTypes.PostalCode) == 0) 
                        { 
                            throw new ArgumentNullException("Zip Authorization is not specified in policy in web.config"); 
                        } 
                        int zip = -1; 
                        bool success = int.TryParse(reader.GetAttribute("Zip"),out zip); 
                        if (!success) 
                        { 
                            throw new ArgumentException("Specified Zip code is invalid - check your web.config"); 
                        } 
                        m_policies[resource] = zip; 
                    } 
                } 
            } 
            public override bool CheckAccess(AuthorizationContext context) 
            { 
                //GET THE IDENTITY 
                //FIND THE POSTALCODE CLAIM'S VALUE IN IT 
                //COMPARE WITH THE POLICY 
                int allowedZip = -1; 
                int requestedZip = -1; 
                Uri webPage = new Uri(context.Resource.First().Value); 
                IClaimsPrincipal principal = (IClaimsPrincipal)HttpContext.Current.User; 
                if (principal == null) 
                { 
                    throw new InvalidOperationException("Principal is not populate in the context - check configuration"); 
                } 
                IClaimsIdentity identity = (IClaimsIdentity)principal.Identity; 
                if (m_policies.ContainsKey(webPage.PathAndQuery)) 
                { 
                    allowedZip = m_policies[webPage.PathAndQuery]; 
                    requestedZip = -1; 
                    int.TryParse((from c in identity.Claims 
                                            where c.ClaimType == ClaimTypes.PostalCode 
                                            select c.Value).FirstOrDefault(), out requestedZip); 
                } 
                if (requestedZip!=allowedZip) 
                { 
                    return false; 
                } 
                return true; 
            } 
        } 
    }
    
  8. 編譯方案,確定沒有任何編譯錯誤。

  9. 尋找已編譯的類別庫,在此案例中為 MyClaimsAuthorizationManager.dll。 需要將它拖曳到 ASP.NET Web 應用程式的 Bin 資料夾。

步驟 2 – 設定 ASP.NET 應用程式,以使用宣告授權庫

下列步驟是在您的 ASP.NET Web 應用程式中執行。 請勿對您在上個步驟中建立之 Claims Authorization Manager 授權庫新增參考。 除了 web.config 以外,您的 ASP.NET Web 應用程式應該「查覺不到」它。

設定 ASAP.NET 應用程式以使用宣告授權庫

  1. 設定您的 ASP.NET Web 應用程式以在它的管線中包括 WIFs ClaimsAuthorizationModule,方法是將下列項目新增到 web.config 的 HttpModules 區段 (適用於 Visual Studio 附隨的開發 Web 伺服器;若為 Internet Information Services (IIS) 第 7 版,此設定應該位於 system.webServer 節點下的模組區段)。

    <add name="ClaimsAuthorizationModule" 
         type="Microsoft.IdentityModel.Web.ClaimsAuthorizationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> 
    
  2. 設定您的 ASP.NET Web 應用程式,以使用您在上個步驟中實作的自訂授權庫,方法是將下列項目新增到 microsoft.identityModel.service 節點。

    <claimsAuthorizationManager type="MyClaimsAuthorizationManager.ZipClaimsAuthorizationManager, MyClaimsAuthorizationManager" >
    

步驟 3 – 設定授權原則

在本主題中,設定原則是以 ASP.NET Web 應用程式的 web.config 檔案來表示。 該原則具備簡單的規則,可將資源對映到宣告類型與它的值。 例如,您在先前幾個步驟建立與設定的自訂授權庫可以讀取與強制實施下列原則。 將下列項目新增到您在上個步驟中設定的 claimsAuthorizationManager 節點。

<policy resource="/default.aspx">
  <claim claimType=https://schemas.xmlsoap.org/ws/2005/05/identity/claims/postalcode
  Zip="11111" />
</policy>

以上原則需要連入權杖具有值為 11111 的郵遞區號宣告,才能存取 dfault.aspx 頁面。