全局授权无效 - 导致呈现空白页面

时间:2012-07-18 14:45:10

标签: asp.net-mvc-3 login global-asax authorize-attribute

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

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

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

}

在我的webconfig中,我添加了:

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

结果是生成的页面完全空白。看看网址,似乎mvc正在按预期重定向到我的登录路由,除了页面为空。如果我将global.asax中的代码注释掉,只需将[Authorize]标记直接放在每个控制器中,它就会按预期工作。

作为一种解决方法,我已经实现了我已经阅读过的MVC2最佳实践,即创建一个BaseController:Controller类,向其添加[Authorize]标记,然后更改所有控制器的inherentences来自BaseController而不是Controller。

现在似乎运作良好。

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

1 个答案:

答案 0 :(得分:3)

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

  1. 您正在导航至/
  2. 您的全局授权属性启动,因为用户未经过身份验证,他会被重定向到~/Account/LogOn(按照您的web.config文件中的说明)进行身份验证
  3. 您的全局授权属性启动,因为用户未经过身份验证,他会被重定向到~/Account/LogOn(按照您的web.config文件中的说明)进行身份验证
  4. 与3相同。
  5. 与4相同。
  6. ...
  7. 我认为你明白了。 LogOn操作应从身份验证中排除,否则用户将永远无法登录您的网站。

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

    所以你可以写一个标记属性:

    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 static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new MyAuthorizeAttribute());  
    }
    

    现在剩下的就是使用我们的标记属性来装饰你想要从身份验证中排除的控制器操作:

    public class AccountController : Controller
    {
        [AllowAnonymous]
        public ActionResult LogOn()
        {
            return View();
        }
    
        [AllowAnonymous]
        [HttpPost]
        public ActionResult LogOn(LogOnModel model, string returnUrl)
        {
            ...
        }
    }