2012-08-07 142 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); 
    } 
}