【问题标题】:How to implement role authorization with custom database?如何使用自定义数据库实现角色授权?
【发布时间】:2020-06-03 00:06:26
【问题描述】:

我有一个应用程序需要使用自定义数据库进行角色授权。数据库设置有一个tblUsers 表,该表引用了tblRoles 表。用户也已分配到他们的角色。

我还想在每个操作上使用[Authorize(Role = "RoleName")] 属性来检查是否已将经过身份验证的用户分配给数据库中的"RoleName"。我很难弄清楚我需要在哪里对[Authorize] 属性进行修改,所以它的行为方式就是这样。我只是想看看用户名是否有角色,我不会有一个页面来管理数据库中的角色。

我已经尝试实现custom storage providers for ASP.NET Core Identity,但它开始看起来不是我需要的,因为我不会在应用程序中管理角色,而且我不知道它如何影响@987654327 的行为@ 属性。

另外,我可能对[Authorize] 属性的工作原理有一个错误的假设。如果你注意到了,如果你能指出来,我将不胜感激。

【问题讨论】:

    标签: asp.net-mvc asp.net-core authorize-attribute asp.net-authorization


    【解决方案1】:

    当我的客户要求为每个角色提供细粒度权限时,我遇到了类似的问题。我找不到修改 Authorize 属性的方法,但能够使用自定义属性实现解决方案。但这取决于一件事,即你能得到调用用户的 userId 吗?我使用了 cookie 身份验证,所以当有人登录时,我只在我的声明中包含 userId,这样当请求到来时,我总是可以从那里获取它。我认为 asp.net 中的内置 Session 逻辑也可以完成这项工作,但我不能肯定地说。无论如何,自定义授权的逻辑是这样的:

    1. 在启动时将用户和角色从数据库加载到缓存。如果您没有在程序中设置缓存(并且不想),您可以通过创建一个包含 2 个静态列表的 UserRoleCache 类来简单地创建自己的缓存。还有几种方法可以在启动时从 db 加载数据,但我发现直接在 Program.cs 中很容易做到这一点,如下所示。
    2. 定义您的自定义属性,通过遍历缓存中的列表来检查调用用户是否具有所需的角色,如果没有则返回 403。

    修改您的 Program 类,如:

        public class Program
        {
            public static async Task Main(string[] args)
            {
                IWebHost webHost = CreateWebHostBuilder(args).Build();
    
                using (var scope = webHost.Services.CreateScope())
                {
                    //Get the DbContext instance. Replace MyDbContext with the 
                    //actual name of the context in your program
                    var context = scope.ServiceProvider.GetRequiredService<MyDbContext>();
    
                    List<User> users = await context.User.ToListAsync();
                    List<Role> roles = await context.Role.ToListAsync();
    
                    //You may make getters and setters, this is just to give you an idea
                    UserRoleCache.users = users;
                    UserRoleCache.roles = roles;
    
                }
    
                webHost.Run();
            }
    
            public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
                WebHost.CreateDefaultBuilder(args)
                    .UseStartup<Startup>();
    
        }
    

    然后是检查用户是否具有角色的逻辑。请注意,我使用了一系列角色,因为有时您希望允许访问多个角色。

        public class RoleRequirementFilter : IAuthorizationFilter
        {
            private readonly string[] _roles;
    
            public PermissionRequirementFilter(string[] roles)
            {
                _roles = roles;
            }
    
            public void OnAuthorization(AuthorizationFilterContext context)
            {
                bool hasRole = false;
    
                //Assuming there's a way you can get the userId
                var userId = GetUserId();
    
                User user = UserRoleCache.users.FirstOrDefault(x => x.Id == userId);
                //Where roleType is the name of the role like Admin, Manager etc
                List<Role> roles = UserRoleCache.roles.FindAll(x => _roles.Contains(x.RoleType))
    
                foreach(var role in roles)
                {
                    if(user.RoleId == role.Id)
                    {
                        hasRole = true;
                        break;
                    }
                }
    
                if (!hasRole)
                    context.Result = new StatusCodeResult(403);
            }
        }
    

    最后制作角色属性

        public class RoleAttribute : TypeFilterAttribute
        {
            public RoleAttribute(params string[] roles) : base(typeof(RoleRequirementFilter))
            {
                Arguments = new object[] { roles };
            }
        }
    

    现在您可以在控制器中使用 Role 属性:

    public class SampleController : ControllerBase
        {
    
            [HttpGet]
            [Role("Admin", "Manager")]
            public async Task<ActionResult> Get()
            {
    
            }
    
            [HttpPost]
            [Role("Admin")]
            public async Task<ActionResult> Post()
            {
    
            }
        }
    

    【讨论】:

      猜你喜欢
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多