【问题标题】:Permissions based on Active Directory Role基于 Active Directory 角色的权限
【发布时间】:2012-08-07 12:21:46
【问题描述】:

我有一个 MVC 应用程序,它使用表单身份验证针对 Active Directory 进行身份验证。随着我的 MVC 应用程序变大,很明显我正在做的角色检查变得越来越分散。我想替换以下内容:

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

类似于以下内容:

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

其中 Permission 是一个枚举。现在我在想我可以像这样定义每个 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 中根据我的 web.config 角色设置检查传入的权限来实现这一点吗? IPrincipal 将具有其 AD 角色,因此确定允许的权限肯定很简单?

任何帮助表示赞赏!

【问题讨论】:

    标签: asp.net-mvc web-config roleprovider


    【解决方案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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-07-26
      • 2015-03-20
      • 2018-05-29
      • 2023-03-15
      • 2021-09-16
      • 2019-12-08
      • 2018-11-17
      • 1970-01-01
      • 2020-03-05
      相关资源
      最近更新 更多