分佈式應用程序的身份驗證和授權方法

基於角色授權

大部分 .NET Web 應用程序都使用基於角色的授權方法。您需要考慮各種角色類型,選擇最適合您的應用程序方案的方法。您有以下選項:

.NET 角色
Enterprise Services (COM+) 角色
SQL Server 用戶定義的數據庫角色
SQL Server 應用程序角色

.NET 角色

.NET 角色非常靈活,它圍繞 IPrincipal 對象展開,這些對象包含通過身份驗證的身份所屬的角色列表。.NET 角色可以用於 Web 應用程序、Web 服務,或駐留在 ASP.NET (用 HttpChannel 訪問)中的遠程組件。

授權可以通過 .NET 角色以兩種方式進行:一種以聲明方式用 PrincipalPermission 命令,一種以編程方式,在代碼中用強制的 PrincipalPermission 命令或 IPrincipal.IsInRole 方法。

Windows 身份驗證中的 .NET 角色

如果您的應用程序使用 Windows 身份驗證,則 ASP.NET 會自動構建一個 WindowsPrincipal,並將其附加到當前 Web 請求的上下文(使用 HttpContext.User)。身份驗證過程完成,並且 ASP.NET 將對象附加到當前請求後,它就可用於所有後續的基於 .NET 角色的授權了。

通過身份驗證的調用者的 Windows 組成員用於確定角色集。在 Windows 身份驗證下,.NET 角色與 Windows 組相同。

非 Windows 身份驗證中的 .NET 角色

如果您的應用程序使用非 Windows 身份驗證機制(例如表單或 Passport),那麼您必須編寫代碼來創建 GenericPrincipal 對象(或自定義 IPrincipal 對象),並用從自定義身份驗證數據存儲(如 SQL Server 數據庫)中獲得的角色集填充它。

自定義 IPrincipal 對象

基於 .NET 角色的安全機制是可擴展的。您可以開發實現 IPrincipalIIdentity 的自有類,並提供您自己的基於角色的擴展授權功能。

只要自定義 IPrincipal 對象(包含從自定義數據存儲中獲得的角色)(通過 HttpContext.User)附加到當前請求的上下文,就保證了基本角色的檢查功能。

通過實現 IPrincipal 接口,可以確保聲明和命令形式的PrincipalPermission 命令都適用於您的自定義身份。另外,您可以實現擴展的角色語義;例如,提供允許您測試和斷言多個角色的成員身份的其他方法,比如 IsInMultipleRoles( string [] roles )。

Enterprise Services (COM+) 角色

使用 Enterprise Services (COM+) 角色可以將訪問檢查交給中間層,並允許您在連接到後端數據庫時使用數據庫連接池。然而,對於有意義的基於 Enterprise Services (COM+) 角色的授權,前端 Web 應用程序必須模擬原調用者的身份,並(通過 Windows 訪問令牌)使將其傳遞到 Enterprise Services 應用程序。爲此,必須在 Web 應用程序的 Web.config 文件中放入以下各項。

<authentication mode="Windows" /> 
<identity impersonate="true" /> 

如果使用方法級的說明性檢查(以確定哪些用戶可以調用哪些方法)就足夠的話,則可以使用“組件服務”管理工具部署應用程序和更新角色成員。

如果需要用方法代碼以編程方式進行檢查,您將會失去 Enterprise Services (COM+) 角色的一些管理和部署優點,因爲角色邏輯是硬編碼的。

SQL Server 用戶定義的數據庫角色

在這種方法中,您在數據庫中創建角色,根據角色指派權限,並將 Windows 組和用戶帳戶映射到角色。這種方法要求您將調用者身份傳遞到後端(如果您對 SQL Server 使用首選的 Windows 身份驗證)。

SQL Server 應用程序角色

在這種方法中,將權限授予數據庫中的角色,但 SQL Server 應用程序角色不包含用戶和組帳戶。因此,您就會失去原調用者的粒度。

在應用程序角色中,您被授權訪問特定的應用程序(與一組用戶相對)。此應用程序使用接受角色名和密碼的內置存儲過程激活角色。這種方法的一個主要缺點是它要求應用程序安全地管理憑證(角色名和相關的密碼)。

.NET 角色與 Enterprise Services (COM+) 角色的對比

以下表格列出 .NET 角色和 Enterprise Services (COM+) 角色的功能對比。

表 2:Enterprise Services 角色與 .NET 角色的對比
功能 Enterprise Services 角色 .NET 角色

管理

組件服務管理工具

自定義

數據存儲

COM+ 目錄

自定義數據存儲(如 SQL Server 或 Active Directory)

聲明性

命令性

類、接口和方法級粒度

可擴展性

是(使用自定義 IPrincipal 實現)

可供所有 .NET 組件使用

只供派生自 ServicedComponent 基類的組件使用

角色成員

角色包含 Windows 組或用戶帳戶

當使用 WindowsPrincipal 時,角色是 Windows 組–—沒有額外的抽象級別

要求顯式地實現接口

是,要想獲得方法級的授權,必須顯式地定義和實現接口

 

使用 .NET 角色

可以使用 .NET 角色保護以下各項的安全:

文件
文件夾
Web 頁面(.aspx 文件)
Web 服務(.asmx 文件)
對象
方法和屬性
方法中的代碼塊

可以使用 .NET 角色保護操作(由方法和屬性執行)和特定代碼塊的事實,意味着您可以保護對應用程序所訪問的本地和遠程資源的訪問。

前面列表中的前四項(文件、文件夾、Web 頁面和 Web 服務)是通過 UrlAuthorizationModule 保護的,它可以使用調用者的角色成員(和調用者的身份)做出授權決定。

如果您使用 Windows 身份驗證,則系統會爲您完成使用 .NET 角色所需的大部分工作。ASP.NET 會構建 WindowsPrincipal 對象,並由用戶的 Windows 組成員確定相關的角色集。

要在非 Windows 身份驗證機制中使用 .NET 角色,必須編寫代碼執行以下操作:

捕獲用戶憑證。
檢驗用戶訪問自定義數據存儲(比如 SQL Server 數據庫)的憑證。
檢索角色列表,構建 GenericPrincipal 對象並將它與當前 Web 請求相關聯。

GenericPrincipal 對象代表通過身份驗證的用戶,並用於後續的 .NET 角色檢查,例如聲明性的PrincipalPermission 命令和編程方式的IPrincipal.IsInRole 檢查。

檢查角色成員

可使用以下類型的 .NET 角色檢查:

重要:.NET 角色檢查依賴於 IPrincipal 對象(表示通過身份驗證的用戶)是否與當前請求關聯。對於 ASP.NET Web 應用程序,IPrincipal 對象必須附加到 HttpContext.User。對於 Windows 窗體應用程序,IPrincipal 對象必須附加到 Thread.CurrentPrincipal

手動角色檢查。對於細分授權,您可以調用 IPrincipal.IsInRole 方法,根據調用者的角色成員授權對特定代碼塊的訪問。在檢查角色成員時,AND 和 OR 邏輯均可使用。
聲明性角色檢查(方法入口)。您可以使用 PrincipalPermissionAttribute 類(可以簡寫爲 PrincipalPermission)對方法進行註釋,以聲明方式請求角色成員。這些檢查只支持 OR 邏輯。例如,您可以要求調用者至少屬於一個特定的角色(例如,調用者必須是出納員或一個經理)。不能用聲明性檢查指定調用者必須既是經理,又是出納員。
命令性角色檢查(在方法中檢查)。可以在代碼中調用 PrincipalPermission.Demand 執行細分授權邏輯。支持邏輯 AND 和 OR 操作。

角色檢查示例

以下代碼片段顯示了一些使用編程、聲明性和命令性方法的角色檢查示例。

授權 Bob 執行操作:

儘管可以授權個別用戶,但通常應該基於角色成員身份進行授權,這使您可以授權在應用程序中共享相同特權的用戶組。

直接用戶名檢查
    GenericIdentity userIdentity = new GenericIdentity("Bob"); 
    if (userIdentity.Name=="Bob") 
    { 
    } 
聲明性檢查
    [PrincipalPermissionAttribute(SecurityAction.Demand, User="Bob")] 
    public void DoPrivilegedMethod() 
    { 
    } 
命令性檢查
    PrincipalPermission permCheckUser = new PrincipalPermission( 
                                                   "Bob", null); 
    permCheckUser.Demand(); 

授權出納員執行操作:

直接角色名檢查
    GenericIdentity userIdentity = new GenericIdentity("Bob"); 
    // Role names would be retrieved from a custom data store 
    string[] roles = new String[]{"Manager", "Teller"}; 
    GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity,  
                                                          roles); 
    if (userPrincipal.IsInRole("Teller")) 
    { 
    } 
聲明性檢查
    [PrincipalPermissionAttribute(SecurityAction.Demand, Role="Teller")] 
    void SomeTellerOnlyMethod() 
    { 
    } 
命令性檢查
    public SomeMethod() 
    { 
      PrincipalPermission permCheck = new PrincipalPermission( 
                                                   null,"Teller"); 
      permCheck.Demand(); 
      // Only Tellers can execute the following code 
      // •ñn members of the Teller role result in a security exception 
      . . . 
    } 

授權經理或出納員執行操作:

直接角色名檢查
    if (Thread.CurrentPrincipal.IsInRole("Teller") || 
        Thread.CurrentPrincipal.IsInRole("Manager")) 
    { 
      // Perform privileged operations 
    } 
聲明性檢查
    [PrincipalPermissionAttribute(SecurityAction.Demand, Role="Teller"), 
     PrincipalPermissionAttribute(SecurityAction.Demand, Role="Manager")] 
    public void DoPrivilegedMethod() 
    { 
    } 
命令性檢查
    PrincipalPermission permCheckTellers = new PrincipalPermission(  
                                                       null,"Teller"); 
    PrincipalPermission permCheckManagers = new PrincipalPermission( 
                                                       null,"Manager"); 
   (permCheckTellers.Union(permCheckManagers)).Demand(); 

授權那些既是經理又是出納員的用戶執行操作:

直接角色名檢查
    if (Thread.CurrentPrincipal.IsInRole("Teller") && 
        Thread.CurrentPrincipal.IsInRole("Manager")) 
    { 
      // Perform privileged operation 
    } 
聲明性檢查

不可以利用 .NET 角色以聲明方式執行 AND 檢查。將 PrincipalPermission 命令疊加在一起使用會產生邏輯 OR。

命令性檢查
    PrincipalPermission permCheckTellers = new PrincipalPermission( 
                                                     null,"Teller"); 
    permCheckTellers.Demand();   
    PrincipalPermission permCheckManagers = new PrincipalPermission( 
                                                     null, "Manager"); 
    permCheckManagers.Demand(); 

 

選擇身份驗證機制

本部分提供指導信息,旨在幫助您選擇常見應用程序方案的身份驗證機制。您應該考慮從以下問題着手:

身份。僅當應用程序用戶的 Windows 帳戶可由受信任的機構進行身份驗證,並且應用程序的 Web 服務器可以訪問該機構時,才適合使用 Windows 身份驗證機制。
憑證管理。Windows 身份驗證的一個主要優點是它使您可以將憑證管理交給操作系統去做。採用非 Windows 方法(如表單身份驗證),您就必須仔細考慮用戶憑證的存儲位置和方式。兩種最常見的方法是使用:
SQL Server 數據庫
Active Directory 中的用戶對象

有關將 SQL Server 用作憑證存儲的安全考慮事項的更多信息,請參考“數據訪問安全性”一章。

有關在自定義數據存儲(包括 Active Directory)中使用表單身份驗證的更多信息,請參考“ASP.NET 安全性”一章。

身份傳遞。您需要實現模擬/委派模式,並在操作系統級的各層間傳遞原調用者的安全上下文嗎?例如,爲了支持審覈或每用戶(粒度)授權。如果需要,您就需要能夠模擬調用者,並將它們的安全上下文委派到下一個下游子系統,如本章前面的“傳遞身份”部分中的“委派”主題所描述的。
瀏覽器類型。您的用戶都有 Internet Explorer 嗎?或者您需要支持使用混合瀏覽器類型的用戶羣?表 3 闡述了哪些身份驗證機制需要 Internet Explorer 瀏覽器,而哪些支持各種常見的瀏覽器類型。
表 3:身份驗證瀏覽器要求
身份驗證類型 是否要求 Internet Explorer 備註

表單

-

Passport

-

集成 Windows(Kerberos 或 NTLM)

Kerberos 還要求客戶端和服務器使用 Windows 2000 或更高版本的操作系統,並且有爲委派配置的帳戶。要想了解更多信息,請參考“How To Implement Kerberos Delegation for Windows 2000”。

基本

基本身份驗證是幾乎所有瀏覽器都支持的 HTTP 1.1 協議的一部分

簡要

-

證書

客戶端要求 X.509 證書

 

Internet 方案

Internet 方案的基本假定條件是:

用戶在服務器域或該服務器可達的受信任域中沒有 Windows 帳戶。
用戶沒有客戶端證書。

圖 4 顯示了一個爲 Internet 方案選擇身份驗證機制的決策樹。


 

圖 4. 爲 Internet 應用程序選擇身份驗證機制

 

有關 Web 服務安全和 WS 安全規範(全球 XML 體系結構 (GXA) 倡議的一部分)的更多信息,請參考“Web Services Security”一章。

表單/ Passport 比較

這一部分總結表單和 Passport 身份驗證的相對優點。

表單身份驗證的優點

支持對照自定義數據存儲(通常爲 SQL Server 數據庫或 Active Directory)的身份驗證。
支持基於角色授權(包括從數據存儲中查找角色)。
與 Web 用戶界面平穩集成。
ASP.NET 提供結構的大部分。與傳統 ASP 相比,需要的自定義代碼相對較少。

Passport 身份驗證的優點

Passport 是一種集中式解決方案。
它不需要應用程序進行憑證管理。
能與基於角色授權方案一起使用。
非常安全,因爲它建立在加密技術之上。

 

Intranet / Extranet 方案

圖 5 顯示了一個可用於幫助爲 Intranet 和 Extranet 應用方案選擇一種身份驗證機制的決策樹。


 

圖 5. 爲 Intranet 和 Extranet 應用程序選擇一種身份驗證機制

 

身份驗證機制比較

以下表格顯示可用的身份驗證機制的比較。

表 4:可用的身份驗證方法
- Basic Digest NTLM Kerberos Certs Forms Passport

用戶在服務器的域中需要 Windows 帳戶

支持委派*

可以

需要 Win2K 客戶端和服務器

以明文形式傳遞憑證(需要 SSL)

支持非 IE 瀏覽器

 

小結

設計分佈式應用程序的身份驗證和授權方法是一項具有挑戰性的任務。在應用程序開發的早期階段,正確設計身份驗證和授權有助於減少許多主要的安全風險。以下總結本章中的信息:

使用受信任子系統資源訪問模式可獲得使用數據庫連接池的益處。
如果您的應用程序沒有使用 Windows 身份驗證,請使用 .NET 角色檢查提供授權。對照自定義數據存儲檢驗憑證,檢索角色列表並創建 GenericPrincipal 對象。將它與當前 Web 請求 (HttpContext.User) 相關聯。
如果您的應用程序使用 Windows 身份驗證,但不使用 Enterprise Services,請使用 .NET 角色。請記住,對於 Windows 身份驗證,.NET 角色爲 Windows 組。
如果您的應用程序使用 Windows 身份驗證和 Enterprise Services,請考慮使用 Enterprise Services (COM+) 角色。
對於使用 Enterprise Services (COM+) 角色的有意義的基於角色授權,原調用者的身份必須傳遞到 Enterprise Services 應用程序。如果從 ASP.NET Web 應用程序中調用 Enterprise Services 應用程序,則意味着 Web 應用程序必須使用 Windows 身份驗證,並配置爲使用模擬。
PrincipalPermission 屬性對方法進行註釋,以聲明方式請求角色成員。如果調用者不在指定的角色中,則不調用該方法,並且產生一個安全異常。
在方法代碼中調用 PrincipalPermission.Demand (或使用 IPrincipal.IsInRole)以獲得細分授權決策。
考慮實現自定義 IPrincipal 對象以獲得其他角色檢查語義。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章