当用户不在授权角色中时,如何提供未授权页面?

时间:2010-02-23 22:50:11

标签: c# asp.net-mvc security roles

我正在使用Authorize这样的属性:

[Authorize (Roles="Admin, User")]
Public ActionResult Index(int id)
{
    // blah
}

当用户不在指定的角色中时,我会收到一个错误页面(找不到资源)。所以我也放了HandleError属性。

[Authorize (Roles="Admin, User"), HandleError]
Public ActionResult Index(int id)
{
    // blah
}

如果用户不在指定的角色,现在进入登录页面。

如果用户未满足其中一个必需的角色,如何让它转到 Unauthorized 页面而不是登录页面?如果发生不同的错误,我如何将该错误与未经授权的错误区分开来并以不同的方式处理它?<​​/ p>

5 个答案:

答案 0 :(得分:27)

将这样的内容添加到您的web.config:

<customErrors mode="On" defaultRedirect="~/Login">
     <error statusCode="401" redirect="~/Unauthorized" />
     <error statusCode="404" redirect="~/PageNotFound" />
</customErrors>

您显然应该创建/PageNotFound/Unauthorized路由,操作和视图。

编辑:对不起,我显然没有彻底理解这个问题。

问题在于,当执行AuthorizeAttribute过滤器时,它会确定用户不符合要求(他/她可能已登录,但角色不正确)。因此,它将响应状态代码设置为401. FormsAuthentication模块拦截了该代码,然后执行重定向。

我看到两种选择:

  1. 禁用defaultRedirect。

  2. 创建自己的IAuthorizationFilter。从AuthorizeAttribute派生并覆盖HandleUnauthorizedRequest。在此方法中,如果用户通过身份验证,请执行重定向到/ Unauthorized

  3. 我也不喜欢:defaultRedirect功能很好,而不是你想要自己实现的东西。第二种方法导致向用户提供视觉上正确的“您未经授权”页面,但HTTP状态代码将不是所需的401。

    我不太了解HttpModules是否可以通过可容忍的黑客来规避这一点。

    编辑2 : 如何以下列方式实现自己的IAuthorizationFilter:从CodePlex下载MVC2代码并“借用”AuthorizeAttribute的代码。将OnAuthorization方法更改为

        public virtual void OnAuthorization(AuthorizationContext filterContext)
        {
            if (AuthorizeCore(filterContext.HttpContext))
            { 
                HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
                cachePolicy.SetProxyMaxAge(new TimeSpan(0));
                cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
            }
            // Is user logged in?
            else if(filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                // Redirect to custom Unauthorized page
                filterContext.Result = new RedirectResult(unauthorizedUrl);
            } 
            else {
                // Handle in the usual way
                HandleUnauthorizedRequest(filterContext);
            }
        }
    

    其中unauthorizedUrl是过滤器上的属性或从Web.config中读取。

    您也可以从AuthorizeAttribute继承并覆盖OnAuthorization,但您最终会编写一些已经在AuthorizeAttribute中的私有方法。

答案 1 :(得分:7)

你可以用两种方式做到这一点:

  1. 指定HandleError属性的错误,并提供应显示的视图:

    [HandleError(ExceptionType = typeof(UnAuthorizedException),  View =“UnauthorizedError”)]

  2. 您可以指定几种不同的ExceptionTypes和视图

    1. 创建自定义ActionFilter,检查凭据,如果用户未经授权,则重定向到控制器:http://web.archive.org/web/20090322055514/http://msdn.microsoft.com/en-us/library/dd381609.aspx

答案 2 :(得分:4)

根据您的问题(可识别用户,但他们的帐户没有足够的特权),403状态代码可能更合适。 401适用于您不知道用户拥有哪些内容的情况。

答案 3 :(得分:3)

HttpUnauthorizedResult(这是AuthorizeAtrribute的重新发送)只是将StatusCode设置为401.因此,您可以在IIS中设置401页面或在web.config中设置自定义错误页面。当然,您还必须确保不需要授权访问自定义错误页面。

答案 4 :(得分:0)

只需覆盖AuthorizeAttribute的HandleUnauthorizedRequest方法即可。如果调用此方法,但用户已通过身份验证,则可以重定向到“未授权”页面。

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { Area = "", Controller = "Error", Action = "Unauthorized" }));
        }
        else
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
    }
}