Asp.net mvc 基于某些标准(而不是用户身份验证)限制对控制器的访问

Asp.net mvc 基于某些标准(而不是用户身份验证)限制对控制器的访问,asp.net-mvc,controller,data-annotations,asp.net-mvc-5,Asp.net Mvc,Controller,Data Annotations,Asp.net Mvc 5,限制访问控制器的正确方法是什么 例如,我可能有“ProductReviewController”,我希望能够检查此控制器在当前存储中是否可访问并已启用。我不是在寻找代码来实现这一点,但我对在不满足此标准的情况下阻止用户访问控制器的方法感兴趣。我希望请求继续进行,就好像控制器从未出现过一样(因此可能会抛出404) 到目前为止,我的想法是: 数据注释,即[IsValidController]。我从哪个属性类派生-Authorize似乎不太合适,我会将其与用户身份验证联系起来。此外,如果不满足标准,我

限制访问控制器的正确方法是什么

例如,我可能有“ProductReviewController”,我希望能够检查此控制器在当前存储中是否可访问并已启用。我不是在寻找代码来实现这一点,但我对在不满足此标准的情况下阻止用户访问控制器的方法感兴趣。我希望请求继续进行,就好像控制器从未出现过一样(因此可能会抛出404)

到目前为止,我的想法是:

  • 数据注释,即
    [IsValidController]
    。我从哪个
    属性
    类派生-Authorize似乎不太合适,我会将其与用户身份验证联系起来。此外,如果不满足标准,我不确定正确的响应是什么(但我想这取决于它派生的
    属性)。我可以把这个数据注释放在我的基本控制器上

  • 找到页面生命周期中较低的位置,如果控制器不符合我的标准,则停止用户点击控制器。i、 e创建我自己的控制器工厂,如第7点所示:

  • 最好的方法是什么

    注意:目前,我倾向于选项1,并使用类似下面代码的
    AuthorizeAttribute
    。但是我觉得我误用了
    authorized属性

    public class IsControllerAccessible : AuthorizeAttribute
    {
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (!CriteriaMet())
                return false;
    
            return true;
        }
    
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary(
                new
                {
                    controller = "Generic",
                    action = "404"
                })
            );
        }
    }
    

    我想你对
    属性
    感到困惑。它是一个动作过滤器,而不是数据注释。数据注释修饰validatioj的模型属性,动作过滤器修饰控制器动作,以检查控制器的上下文,并在动作执行之前执行某些操作

    因此,限制对控制器操作的访问是
    authorized属性
    存在的理由,所以让我们使用它吧

    在SO好心人的帮助下,我创建了一个客户操作过滤器,该过滤器基于访问目录组的一部分来限制对操作(甚至控制器)的访问:

    public class AuthorizeADAttribute : AuthorizeAttribute
    {
        public string Groups { get; set; }
    
        protected override bool AuthorizeCore(HttpContextBase httpContext)
        {
            if (base.AuthorizeCore(httpContext))
            {
                /* Return true immediately if the authorization is not 
                locked down to any particular AD group */
                if (String.IsNullOrEmpty(Groups))
                    return true;
    
                // Get the AD groups
                var groups = Groups.Split(',').ToList<string>();
    
                // Verify that the user is in the given AD group (if any)
                var context = new PrincipalContext(ContextType.Domain, "YOURADCONTROLLER");
                var userPrincipal = UserPrincipal.FindByIdentity(context,
                                                     IdentityType.SamAccountName,
                                                     httpContext.User.Identity.Name);
    
                foreach (var group in groups)
                {
                    try
                    {
                        if (userPrincipal.IsMemberOf(context, IdentityType.Name, group))
                            return true;
                    }
                    catch (NoMatchingPrincipalException exc)
                    {
                        var msg = String.Format("While authenticating a user, the operation failed due to the group {0} could not be found in Active Directory.", group);
                        System.ApplicationException e = new System.ApplicationException(msg, exc);
                        ErrorSignal.FromCurrentContext().Raise(e);
                        return false;
                    }
                    catch (Exception exc)
                    {
                        var msg = "While authenticating a user, the operation failed.";
                        System.ApplicationException e = new System.ApplicationException(msg, exc);
                        ErrorSignal.FromCurrentContext().Raise(e);
                        return false;
                    }
                }
            }
            return false;
        }
    }
    
    或在控制器级别:

    [AuthorizeAD(Groups = "Admin")]
    public class AdminController : Controller
    
    甚至可以通过在`/App\u Start'中编辑
    FilterConfig.cs
    进行全局编辑:

    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new Code.Filters.MVC.AuthorizeADAttribute() { Groups = "User, Editor, Contributor, Admin" });
        }
    
    太棒了


    另外,您在第二点中提到了页面生命周期。MVC中没有这样的东西,至少在Web表单的意义上你可能不会这么想。这对我来说是一件好事,因为事情已经大大简化了,我不需要记住十几个不同的生命周期事件,也不需要记住每一个事件都是为了什么

    好的,感谢您对数据注释的澄清-我的术语有误。我刚刚使用
    authorized属性编写了自己的版本,它运行良好。我只是想确定这是正确的方法。当我提到生命周期时,我指的是这类事情:。我特别考虑覆盖第7点并创建自定义控制器工厂。在我的情况下,p.s
    404 not found
    将是正确的响应。不是用户未经授权,而是网站不应该显示内容(这意味着用户遵循缓存链接或其他内容)。那么代码可能应该驻留在控制器本身,因为它负责根据用户交互提供正确的视图。如果用户提供产品id,则让控制器检查其在商店中是否存在,如果没有,则重定向到指示该id的特定视图。
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new Code.Filters.MVC.AuthorizeADAttribute() { Groups = "User, Editor, Contributor, Admin" });
        }