首页 文章

ASP.NET身份的动态访问控制

提问于
浏览
2

也许我在ASP.NET Identity(2.2.1)的“文档”中忽略了这一点,但我很难看到创建用于管理角色的控制器和接口的重点 . 我理解管理用户的观点(CRUD分配角色),但就角色的CRUD而言,除非有一种方法可以在运行时为控制器动态检测访问(IsInRole),因此对我来说没有意义 . 我有两个问题:

1]如果必须首先在代码中配置应用程序以设置 Authorize 属性甚至设置应具有访问权限的角色,那么是否有资源和时间专门为角色创建CRUD?

2]有没有办法捕获用户从控制器甚至控制器实例请求操作的时刻,以便可能从DB检查该点的权限?

2 回答

  • 1

    我能在SO上找到的最佳答案是:

    Dynamically add roles to authorize attribute for controller

    这正是我想要完成的,这证明了我为角色创建CRUD的设计是正确的 . 此时,由于我可以使用上述方法动态地将角色添加到Controller,因此我可以动态创建角色,然后将其包含在Controller的要求中以加强访问 .

  • 0
    • 我发现角色非常有用 . 我没有装饰每个控制器,而是将角色装饰放在我为网站的每个部分定义的抽象类上 . 然后,一个部分中使用的每个控制器都继承自该部分的抽象类 .

    • 您可以使用Http模块执行此操作并覆盖AuthorizeRequest事件 . 但我不认为对每个请求进行数据库查询都是个好主意 . 角色存在于内存中,因此角色授权将更加高效 .

    编辑:
    根据您的评论,您可以创建自定义属性来执行此操作 . 以下是我对如何做到的想法 . 在OnAuthorization事件中,我将为每个角色创建一个if块 . 如果用户是该角色的成员,请检查该角色是否可以访问当前控制器 . 该示例演示了仅一个名为Admin的角色的想法 .

    using System.Web.Mvc;
    using System.Security.Claims;
    
    namespace MyApp.Filters
    {
        public class CustomAttribute : AuthorizeAttribute
        {
            private List<string> adminControllers;
    
            public CustomAttribute()
            {
                this.adminControllers = new List<string>();
    
                //This would be a DB call
                this.adminControllers.Add("MyApp.Controllers.AccountController");
                this.adminControllers.Add("MyApp.Controllers.AdministrationController");
            }
    
            public override void OnAuthorization(AuthorizationContext filterContext)
            {
                base.OnAuthorization(filterContext);
    
                //Get the roles for the current user
                var identity = (ClaimsIdentity)filterContext.HttpContext.User.Identity;
                var roles = identity.Claims.Where(c => c.Type == ClaimTypes.Role)
                            .Select(c => c.Value).ToList();
    
                //Check if current user has the Admin role
                if (roles.Contains("Admin"))
                {
                    //Check if Admin role has access to current controller
                    if (this.adminControllers.Contains(filterContext.Controller.ToString()))
                    {
                        filterContext.Result = new RedirectResult("~/Home/Error");
                    }
                }
    
    
            }
        }
    }
    

相关问题