Duncan,
這是我在每個應用程序中遇到的情況。以下是一些背景:我在一所大學的一個部門工作,因此我們必須處理多個數據源。我們的大多數應用程序都具有安全性,可以集成大學「中央IT」安全服務,如集中式身份驗證和活動目錄,以及「本土」角色和權限。
我們的應用程序需要根據「本地」應用程序(在本部門內部使用)和企業數據中的數據爲不同用戶提供不同的視圖和操作。
我們的方法: 在四處尋找並找不到任何地方的這個問題的良好解決方案後,我最終編寫了一個安全框架供我們使用。我不妨繼續介紹它在這裏的作用。以下是涉及的內容:
- 靜態和動態角色。靜態角色獨立於數據(例如,我在應用程序中獲得開發人員角色),而動態角色依賴於SecurityContext(例如,部門的財務官員在查看其部門帳戶時會獲得'財務官員角色')。
- 分配給靜態角色或動態角色的權限。
- 一個SecurityContext,封裝了執行權限檢查所需的所有數據,包括當前用戶和任何數據(例如賬號,提案文檔ID,交易日期,任何數據)。
- SecurityContextValidator,接受SecurityContext並返回對指定的SecurityContext中指定的User有效的一個或多個Roles。所以這個邏輯決定了誰能看到這個班上的內容。
- 每個SecurityContext一個SecurityContextValidator。這個映射是在初始化時用SecurityContextManager註冊的。我使用Ninject加載啓動時執行此操作的安全模塊。
- 如果權限未指定SecurityContext(僅包含Asp.Net安全性的Principal信息),則使用默認上下文。
- 給定用戶,SecurityContext和權限的SecurityService確定用戶在該SecurityContext中擁有的所有角色,並檢查是否有任何角色檢查了權限。
在這一點上,這裏是在Asp.Net MVC中的示例流程:
- 接收的HttpRequest
- 通過窗體身份驗證身份驗證
- 路由到控制器動作
- 如果(Permission.GetByName (「CanDoSomething」)。IsAllowed()){//繼續
- 裏面Permission.IsAllowed] -
- SecurityService接收的SecurityContext
- 查找SecurityContextValidator指定的SecurityContext
- 聚集來自SecurityContextValidator
- 遍歷角色的所有靜態和動態的角色,並檢查其中是否有被許可請求。
- 返回True或False!
爲了方便起見,我把它一步,創造了一個AbstractContextProtectedAttribute,這需要一個SecurityContextFactory委託,它可以創建一個SecurityContext的(給定的HTTPRequest,例如)和權限檢查與指定的SecurityContext中。這個類的子類可以用來修飾控制器動作。
唷!因此,現在讓我們設置一個用戶,角色,權限表並將它們映射到對方,定義數據庫中的所有權限。我編寫了一個可插入的SecurityPersistenceService,使得安全框架不再需要使用持久性策略 - 我們不幸擁有從DataReaders,DataAdapters到Linq2Sql和EF的所有內容。但至少我們可以這樣寫代碼:
[Protected("CanAccessX")] // Checks using default context
public class SomeController
{
[Protected("CanSeeY")] // Checks using default context
public PartialViewResult GetY(<parameters>)
{
var canSeeY_Variation1 = Permission.Get("CanSeeY_Variation1") ;
var y_Variation1_Context = new Y_Variation1_Context { <build your context here> } ;
if (canSeeY_Variation1.IsAllowed(y_variation1_Context))
{
<return variation 1 view>
}
// Y_Variation_2...etc
}
}
而要完成這項工作,在啓動時我註冊相應的驗證:
public class MyNinjectModule
{
public override void Load()
{
// Wire up a persistence service for the security framework
// to use.
SecurityService.SecurityPersistenceService = new MySecurityPersistenceServiceImplementation() ;
// This is what allows the SecurityService to figure out what Validator to use
// in a specified Context to get the User's Roles.
SecurityService.RegisterValidator<Y_Variation1_Context>(new Y_Variation1_ContextValidator(...)) ;
}
}
我現在工作的除了這個框架,讓我們我對數據的枚舉進行這些檢查,從而爲我的所有域對象注入安全基礎結構。我知道這樣做的唯一干淨方式就是使用AOP。我曾經在Java中工作並使用過AspectJ。現在我正在考慮PostSharp。
希望這可以爲您思考問題提供視角。
嗨,你的問題很有趣,但相當抽象。請給我們幾個詳細的例子嗎? – 2011-10-11 19:28:57