18

我已经在 ASP.NET MVC 站点中实现了错误处理,就像这篇文章所建议的那样

404错误一切正常。但是如何正确显示401 错误的用户友好屏幕?它们通常不会抛出可以在内部处理的异常,Application_Error()而是操作返回 HttpUnauthorizedResult。一种可能的方法是将以下代码添加到Application_EndRequest()方法的末尾

if (Context.Response.StatusCode == 401)
{
    throw new HttpException(401, "You are not authorised");
    // or UserFriendlyErrorRedirect(new HttpException(401, "You are not authorised")), witout exception
}

但是在Application_EndRequest()Context.Session == null 内部,errorController.Execute()由于无法使用默认的 TempDataProvider 而失败。

  // Call target Controller and pass the routeData.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData)); // Additional information: The SessionStateTempDataProvider requires SessionState to be enabled.

那么,您能否建议一些如何在 ASP.NET MVC 应用程序中“用户友好地处理”401 的最佳实践?

谢谢。

4

4 回答 4

14

查看 HandleErrorAttribute。从它子类化或添加您自己的实现,它将处理您感兴趣的所有状态代码。您可以使其为每种错误类型返回一个单独的错误视图。

以下是如何创建句柄错误异常过滤器的想法。我已经扔掉了大部分东西,只专注于我们的必需品。绝对看看原始实现以添加参数检查和其他重要的事情。

public class HandleManyErrorsAttribute : FilterAttribute, IExceptionFilter
{
    public virtual void OnException(ExceptionContext filterContext)
    {
        if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
            return;

        Exception exception = filterContext.Exception;

        string viewName = string.Empty;
        object viewModel = null;
        int httpCode = new HttpException(null, exception).GetHttpCode();
        if (httpCode == 500)
        {
            viewName = "Error500View";
            viewModel = new Error500Model();
        }
        else if (httpCode == 404)
        {
            viewName = "Error404View";
            viewModel = new Error404Model();
        }
        else if (httpCode == 401)
        {
            viewName = "Error401View";
            viewModel = new Error401Model();
        }

        string controllerName = (string)filterContext.RouteData.Values["controller"];
        string actionName = (string)filterContext.RouteData.Values["action"];
        filterContext.Result = new ViewResult
        {
            ViewName = viewName,
            MasterName = Master,
            ViewData = viewModel,
            TempData = filterContext.Controller.TempData
        };
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.StatusCode = httpCode;

        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

然后你用这个属性“装饰”你的控制器动作:

[HandleManyErrors]
public ActionResult DoSomethingBuggy ()
{
    // ...
}
于 2009-11-05T11:20:51.467 回答
6

我设法以一种非常简单的方式解决了这个问题。我想为登录用户显示一个自定义页面(“你没有权限 bla bla ...”)并将未经身份验证的用户重定向到登录页面(默认行为)。因此,我实现了一个自定义 AuthorizeAttribute(比如 CustomAuthorizeAttribute),并覆盖了 HandleUnauthorizedRequest 方法,如果用户通过身份验证,我使用名为 AccessDenied.aspx 的 ViewResult(在共享文件夹中)设置 filterContext 参数的 Result 属性

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
    if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
    else
    {
        filterContext.Result = new ViewResult { ViewName = "AccessDenied" };
    }
}

然后你必须改用这个新属性。问候。

于 2010-01-22T12:54:52.380 回答
0

如果您使用的是 ASP.NET MVC,那么您很可能会使用 IIS,那么为什么不将 IIS 设置为使用该 Web 应用程序/虚拟目录的自定义 401 错误页面呢?

于 2009-11-05T11:40:41.300 回答
-1

在我的一个项目中,我使用来自uvita的代码。

我有ASP.NET MVC2,我使用没有登录页面的Active Directory身份验证。我有一个使用站点母版页的NoAuth.aspx页面,集成了 Web 应用程序布局。

这是 web.config。

<system.web>
    <authentication mode="Windows" />
    <roleManager enabled="true" defaultProvider="AspNetWindowsTokenRoleProvider">
       <providers>
          <clear />
          <add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider"
          applicationName="/" />
      </providers>
    </roleManager>
</system.web>

新类 CustomAutorizeAttribute

using System.Web.Mvc;
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
        {
            base.HandleUnauthorizedRequest(filterContext);
        }
        else
        {
           filterContext.Result = new ViewResult { ViewName = "NoAuth"};
        }
    }
}

和控制器

[CustomAuthorize(Roles = "ADRole")]
public class HomeController : Controller
{
    public HomeController()
    {
    }
}
于 2015-10-19T14:15:58.890 回答