在[授权]失败后显示404错误页面

时间:2012-02-29 17:09:03

标签: asp.net-mvc asp.net-mvc-3 error-handling authorization

我有一个动作,我想只限制角色“Admin”。我是这样做的:

[Authorize(Roles = "Admin")]
public ActionResult Edit(int id)

手动进入Controller / Edit / 1路径后,我被重定向到登录页面。嗯,这也许不错,但我想显示404而不是它,并尝试坚持使用属性。这可能吗?

2 个答案:

答案 0 :(得分:14)

  

这可能吗?

当然,您可以编写自定义授权属性:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new ViewResult
        {
            ViewName = "~/Views/Shared/401.cshtml"
        };
    }
}

然后使用它:

[MyAuthorize(Roles = "Admin")]
public ActionResult Edit(int id)

备注:如果用户未获得授权,您可能希望显示401或403页面而不是404,而该文件未找到。

答案 1 :(得分:1)

回应@ Daniel对我对@ Darin的回答的评论,这是我的实施:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        string cookieName = FormsAuthentication.FormsCookieName;

        if (!filterContext.HttpContext.User.Identity.IsAuthenticated ||
            filterContext.HttpContext.Request.Cookies == null ||
            filterContext.HttpContext.Request.Cookies[cookieName] == null
        )
        {
            HandleUnauthorizedRequest(filterContext);
            return;
        }

        var authCookie = filterContext.HttpContext.Request.Cookies[cookieName];
        var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        string[] roles = authTicket.UserData.Split(',');

        var userIdentity = new GenericIdentity(authTicket.Name);
        var userPrincipal = new GenericPrincipal(userIdentity, roles);

        filterContext.HttpContext.User = userPrincipal;
        base.OnAuthorization(filterContext);
    }

    // Redirects unauthorized users to a "401 Unauthorized" page
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.Result = new ViewResult
        {
            ViewName = "~/Views/Shared/Error/401.cshtml"
        };
    }
}