Asp.net mvc 3 全局授权不起作用-导致呈现空白页

Asp.net mvc 3 全局授权不起作用-导致呈现空白页,asp.net-mvc-3,login,global-asax,authorize-attribute,Asp.net Mvc 3,Login,Global Asax,Authorize Attribute,我正在尝试为我的MVC3站点实现一个非常基本的登录方案。如果我理解正确,我应该能够实现一个全局设置,而不是将[Authorize]标记添加到每个控制器类中。为此,我在global.asax中添加了以下内容: protected void Application_Start() { RegisterGlobalFilters(GlobalFilters.Filters); } public static void RegisterGlobalFilters(GlobalFilterCol

我正在尝试为我的MVC3站点实现一个非常基本的登录方案。如果我理解正确,我应该能够实现一个全局设置,而不是将[Authorize]标记添加到每个控制器类中。为此,我在global.asax中添加了以下内容:

protected void Application_Start()
{
    RegisterGlobalFilters(GlobalFilters.Filters);
}

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new AuthorizeAttribute());  

}
在我的网络配置中,我补充道:

<authentication mode="Forms">
   <forms loginUrl="~/Account/LogOn" timeout="2880" />
</authentication>

结果是生成的页面完全为空。查看url,mvc似乎正在按预期重定向到我的登录路径,但页面为空。如果我注释掉global.asax中的代码,并将[Authorize]标记直接放在每个控件中,它将按预期工作

作为一种解决方法,我实现了我读过的MVC2最佳实践,即创建一个BaseController:Controller类,向其中添加[Authorize]标记,然后将我所有控制器的固有性更改为inheret from BaseController而不是Controller

目前看来,这种方法已经足够有效了


但是为什么global.asax的实现不起作用呢?

让我们看看这里发生了什么:

  • 您正在导航到
    /
  • 您的“全局授权”属性生效,由于用户未经过身份验证,因此会将其重定向到
    ~/Account/LogOn
    (按照web.config文件中的说明)进行身份验证
  • 您的“全局授权”属性生效,由于用户未经过身份验证,因此会将其重定向到
    ~/Account/LogOn
    (按照web.config文件中的说明)进行身份验证
  • 与3相同
  • 与4相同
  • 我想你明白了。
    登录
    操作应排除在身份验证之外,否则用户将永远无法登录到您的网站

    由于您已全局应用了Authorize属性,因此无法执行此操作。一种可能的方法是编写一个自定义authorized属性,该属性将全局应用,并将此操作从身份验证中排除

    因此,您可以编写一个标记属性:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    
    和全局自定义授权属性:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    
    将在以下地点登记:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyAuthorizeAttribute());  
    }
    
    现在,您只需使用标记属性来修饰要从身份验证中排除的控制器操作:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    

    让我们看看这里发生了什么:

  • 您正在导航到
    /
  • 您的“全局授权”属性生效,由于用户未经过身份验证,因此会将其重定向到
    ~/Account/LogOn
    (按照web.config文件中的说明)进行身份验证
  • 您的“全局授权”属性生效,由于用户未经过身份验证,因此会将其重定向到
    ~/Account/LogOn
    (按照web.config文件中的说明)进行身份验证
  • 与3相同
  • 与4相同
  • 我想你明白了。
    登录
    操作应排除在身份验证之外,否则用户将永远无法登录到您的网站

    由于您已全局应用了Authorize属性,因此无法执行此操作。一种可能的方法是编写一个自定义authorized属性,该属性将全局应用,并将此操作从身份验证中排除

    因此,您可以编写一个标记属性:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    
    和全局自定义授权属性:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    
    将在以下地点登记:

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyAuthorizeAttribute());  
    }
    
    现在,您只需使用标记属性来修饰要从身份验证中排除的控制器操作:

    public class AllowAnonymousAttribute : Attribute
    {
    }
    
    public class MyAuthorizeAttribute : AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            var exclude = ((AllowAnonymousAttribute[])filterContext.ActionDescriptor.GetCustomAttributes(typeof(AllowAnonymousAttribute), false)).Any();
            if (!exclude)
            {
                base.OnAuthorization(filterContext);
            }
        }
    }
    
    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }
    

    谢谢你,达林,这当然是非常清楚的安排,帮助很大。非常感谢。@NewJoizey,你设法让它工作了吗?关于这个问题,你还有其他问题吗?达林,谢谢你的跟进。我在最初的帖子中提到,我确实使用MVC2解决方案完成了这项工作,这在目前来说已经足够好了。我无法理解观察到的行为背后的“为什么”,但你在“让我们看看这里发生了什么”下解释了这一点。现在我明白了,我可能会把它留给未来的重构来实现。谢谢Darin,这当然是非常清楚的,而且非常有帮助。非常感谢。@NewJoizey,你设法让它工作了吗?关于这个问题,你还有其他问题吗?达林,谢谢你的跟进。我在最初的帖子中提到,我确实使用MVC2解决方案完成了这项工作,这在目前来说已经足够好了。我无法理解观察到的行为背后的“为什么”,但你在“让我们看看这里发生了什么”下解释了这一点。现在我明白了,我可能会把它留给未来的重构来实现。