2012-08-07 120 views
3

我有一個MVC應用程序使用Forms身份驗證對Active Directory進行身份驗證。由於我的MVC應用程序的規模已經很大,顯而易見的是,我正在檢查的角色越來越分散。我想更換喜歡的事物:沿東西線基於Active Directory角色的權限

[Authorize(Roles = "Staff")]Thread.CurrentPrincipal.IsInRole("Staff")

[AuthorizePermission(Permission.CanDoSomething)]Thead.CurrentPrincipal.HasPermission(Permission.CanDoSomething)

許可被枚舉。現在,我在想,我可以定義每個AD角色有哪些權限在web.config中像這樣:

<role name="Staff"> 
    <permissions> 
     <add name="CreateEditDeleteSomething" /> 
     <add name="PublishSomething" /> 
     <add name="QueryUsers" /> 
    </permissions> 
    </role> 

然後我可以實現一個IPrincipal擴展方法 - HasPermission(Permission permission)。這將查看用戶是否記錄到任何具有web.config中定義的權限的AD組。這將允許我更改特定AD組的權限,而無需更改代碼或更新現有測試。自定義的授權屬性然後可以調用HasPermission方法。

這種方法是否正確或是否有更好的方法來簡化我在應用程序中的角色?我在網絡上和網絡上看到了很多例子,但它們似乎過於複雜。我可以通過在HasPermission中檢查傳遞給Permission的web.config角色設置來實現嗎? IPrincipal將有它的AD角色,所以確定它很容易確定允許的權限?

任何幫助表示讚賞!

回答

1

權限比角色複雜得多。

有往往是權限組,如CreateEditDelete ......但他們也可以是顆粒狀的子集,如只是「創建」,「編輯」,「刪除」

我會解決這個問題的方式創建一個PermissionsManger類,該類可以確定用戶應該賦予業務規則上下文和AD角色的權限。

我使用按位標誌來幫助簡化細化權限的複雜性。

如何將角色映射到權限完全取決於您。

using System; 
using System.Linq; 
using System.Security.Principal; 

// Install-Package FluentAssertions -Pre 
using FluentAssertions; 

public static class ExtensionsForIPrincipal 
{ 
    public static bool HasPermission(this IPrincipal principal, Permissions permission) 
    { 
     return PermissionsManager.GetUserPermissions(principal).HasFlag(permission); 
    } 

    public static bool IsInRole(this IPrincipal principal, params string[] roleNames) 
    { 
     return roleNames.Any(principal.IsInRole); 
    } 
} 

public static class PermissionsManager 
{ 
    public static Permissions GetUserPermissions(IPrincipal user) 
    { 
     if (user.IsInRole("admin")) 
     { 
      return Permissions.All; 
     } 

     var userPermissions = Permissions.None; 

     if (user.IsInRole("staff", "user")) 
     { 
      userPermissions |= Permissions.QueryUsers; 
     } 

     if (user.IsInRole("staff")) 
     { 
      userPermissions |= Permissions.PermissionsCreateEditDeleteSomething | Permissions.QueryUsers; 
     } 

     if (user.IsInRole("editor")) 
     { 
      userPermissions |= Permissions.PublishSomething; 
     } 

     return userPermissions; 
    } 
} 

[Flags] 
public enum Permissions 
{ 
    None = 0, 
    CreateSomething = 1, 
    EditSomething = 2, 
    DeleteSomething = 4, 
    PublishSomething = 8, 
    QueryUsers = 16, 
    PermissionsCreateEditDeleteSomething = CreateSomething | EditSomething | DeleteSomething, 
    All = PermissionsCreateEditDeleteSomething | PublishSomething | QueryUsers 
} 

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     IPrincipal admin = Create("james", "admin"); 

     PermissionsManager.GetUserPermissions(admin).ShouldBeEquivalentTo(Permissions.All); 

     admin.HasPermission(Permissions.None).Should().BeTrue(); 
     admin.HasPermission(Permissions.EditSomething).Should().BeTrue(); 
     admin.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue(); 
     admin.HasPermission(Permissions.PublishSomething).Should().BeTrue(); 
     admin.HasPermission(Permissions.QueryUsers).Should().BeTrue(); 
     admin.HasPermission(Permissions.All).Should().BeTrue(); 

     IPrincipal editor = Create("susan", "editor", "staff"); 

     editor.HasPermission(Permissions.None).Should().BeTrue(); 
     editor.HasPermission(Permissions.EditSomething).Should().BeTrue(); 
     editor.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue(); 
     editor.HasPermission(Permissions.QueryUsers).Should().BeTrue(); 
     editor.HasPermission(Permissions.PublishSomething).Should().BeTrue(); 
     editor.HasPermission(Permissions.All).Should().BeTrue(); 

     IPrincipal staff = Create("michael", "staff"); 

     staff.HasPermission(Permissions.None).Should().BeTrue(); 
     staff.HasPermission(Permissions.EditSomething | Permissions.DeleteSomething).Should().BeTrue(); 
     staff.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeTrue(); 
     staff.HasPermission(Permissions.QueryUsers).Should().BeTrue(); 
     staff.HasPermission(Permissions.PublishSomething).Should().BeFalse(); 
     staff.HasPermission(Permissions.All).Should().BeFalse(); 

     IPrincipal user = Create("bob", "user"); 

     user.HasPermission(Permissions.None).Should().BeTrue(); 
     user.HasPermission(Permissions.EditSomething).Should().BeFalse(); 
     user.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeFalse(); 
     user.HasPermission(Permissions.QueryUsers).Should().BeTrue(); 
     user.HasPermission(Permissions.PublishSomething).Should().BeFalse(); 
     user.HasPermission(Permissions.All).Should().BeFalse(); 

     IPrincipal anon = Create("anonymous"); 

     anon.HasPermission(Permissions.None).Should().BeTrue(); 
     anon.HasPermission(Permissions.EditSomething).Should().BeFalse(); 
     anon.HasPermission(Permissions.PermissionsCreateEditDeleteSomething).Should().BeFalse(); 
     anon.HasPermission(Permissions.QueryUsers).Should().BeFalse(); 
     anon.HasPermission(Permissions.PublishSomething).Should().BeFalse(); 
     anon.HasPermission(Permissions.All).Should().BeFalse(); 

     Console.WriteLine("All tests passed"); 
     Console.ReadLine(); 
    } 

    private static IPrincipal Create(string name, params string[] roles) 
    { 
     return new GenericPrincipal(new GenericIdentity(name), roles); 
    } 
}