如何使用自定义数据库实现角色授权? [英] How to implement role authorization with custom database?

查看:80
本文介绍了如何使用自定义数据库实现角色授权?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要使用自定义数据库进行角色授权的应用程序.数据库是用 tblUsers 表建立的,该表具有对 tblRoles 表的引用.用户也已经分配了他们的角色.

I have an application which requires role authorization using custom database. The database is set up with a tblUsers table that has a reference to a tblRoles table. The users are also already assigned to their roles.

我还想在每个操作上使用 [Authorize(Role ="RoleName")] 属性,以检查是否将经过身份验证的用户分配给了"RoleName" 数据库.我在弄清楚需要在哪里修改 [Authorize] 属性的方式时遇到了很多麻烦.我只想看看用户名是否具有角色,就没有一个页面来管理数据库中的角色.

I also want to use the [Authorize(Role = "RoleName")] attribute on each action to check if an authenticated user is assigned to "RoleName" in the database. I'm having a lot of trouble figuring out where I need to make a modification to the [Authorize] attribute so it behaves that way. I just want to see if a username has a role, I won't have a page to manage roles in the database.

我尝试实施

I have tried implementing custom storage providers for ASP.NET Core Identity, but it's starting to look like this is not what I need because I'm not gonna be managing roles within the application, and I can't tell how it affects the behavior of [Authorize] attribute.

此外,在理解 [Authorize] 属性的工作方式时,我可能有一个错误的假设.如果您注意到了,请指出.

Also, it's likely that I have a false assumption in my understanding on how the [Authorize] attribute even works. If you notice it, I would appreciate if you could point it out.

推荐答案

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

I had a similar problem when my client asked for granular permissions for each role. I couldn't find a way to modify the Authorize attribute but was able to implement the solution with a custom attribute. But it depends on one thing i.e can you get the userId of the calling user? I used cookie authentication so I just include the userId in my claims when someone logs in so when a request comes I can always get it from there. I think the built-in Session logic in asp.net might get the job done too, I can't say for sure though. Anyways the logic for custom authorization goes like this:

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

修改您的Program类,例如:

Modify your Program class like:

    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>();

    }

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

Then comes the logic for checking if user has a role. Notice I've used an array of roles because sometimes you'll want to allow access to multiple roles.

    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属性:

Now you can use the Role attribute in your controllers:

public class SampleController : ControllerBase
    {

        [HttpGet]
        [Role("Admin", "Manager")]
        public async Task<ActionResult> Get()
        {

        }

        [HttpPost]
        [Role("Admin")]
        public async Task<ActionResult> Post()
        {

        }
    }

这篇关于如何使用自定义数据库实现角色授权?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆