【问题标题】:Capture exceptions from Authorize attribute in MVC4从 MVC4 中的 Authorize 属性捕获异常
【发布时间】:2014-01-23 14:31:24
【问题描述】:

我使用 Windows 身份验证在我的 MVC4 应用程序中添加了 Authorise attribute,在测试时我更改了活动目录组的名称以检查 Global.asax 类中的 Application_Error 方法是否会捕获非授权用户.

问题是没有捕获到异常,IIS express 抛出了 401 异常。这些类型的授权异常是否可以被捕获,如果可以,是否有更好的方法来处理 MVC 应用程序中的异常?

方法

全球 asax

protected void Application_Error()
{
    System.Diagnostics.Debugger.Break();
}

IIS express 抛出 401 未授权异常

工作验证

使用此方法可行,但有点混乱。

if (User.IsInRole(@"DOMAIN\USER"))
{
    if (ModelState.IsValid)
    {
        ctx.SaveChanges(model);
        ViewBag.Notification = "Save Successful";
    }
}
else
{
    throw new HttpException(404, "Category not found");
}

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-4 exception


    【解决方案1】:

    经过进一步研究,我在Part1Part2 中发现了来自Michael Mckenna 的几篇博文,他详细介绍了他的异常处理策略,我必须通过手动测试来解决用户是否在活动目录组中并且如果不抛出HTTPException

    这解决了问题,但在使用 AuthorizeAttribute 时仍然没有捕获任何异常

    Global.asax

     protected void Application_Error()
        {
            var exception = Server.GetLastError();
            Server.ClearError();
            var httpException = exception as HttpException;
    
            //Logging goes here
    
            var routeData = new RouteData();
            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = "Index";
    
            if (httpException != null)
            {
                switch(httpException.GetHttpCode())
                {
                    case 401:
                        routeData.Values["action"] = "NotAuthorised";
                        break;
                    case 402:
                    case 403:
                        routeData.Values["action"] = "NotAuthorised";
                        break;
                    case 404:
                        routeData.Values["action"] = "NotFound";
                        break;
                }
    
                Response.StatusCode = httpException.GetHttpCode();
            }
            else
            {
                Response.StatusCode = 500;
            }
    
            // Avoid IIS7 getting involved
            Response.TrySkipIisCustomErrors = true;
    
            // Execute the error controller
            IController errorsController = new Jmp.StaticMeasures.Controllers.ErrorController();
            HttpContextWrapper wrapper = new HttpContextWrapper(Context);
            var rc = new RequestContext(wrapper, routeData);
            errorsController.Execute(rc);
        }
    

    错误控制器

    using System.Web.Mvc;
    
        namespace Jmp.StaticMeasures.Controllers
        {
            public class ErrorController : Controller
            {
                public ActionResult Index()
                {
                    return View();
                }
    
                public ActionResult NotFound()
                {
                    return View();
                }
    
                public ActionResult NotAuthorised()
                {
                    return View();
                }
    
            }
        }
    

    【讨论】:

    • 默认的 Authorize-attribute 不会抛出任何异常。但就像我在回答中建议的那样,您可以轻松实现 AuthorizeAttribute 的自定义版本,然后从 HandleUnauthorizedRequest 方法中抛出所需的 HTTPException。
    • 如果我假设“HandleUnauthorizedRequest”方法,特别是“actionContext.ControllerContext.Request.CreateErrorResponse”行确实在响应中包装了一个异常。浏览器在响应头中捕获的内容。
    • 这些方法只是将 401 状态码发送到浏览器。它们不会抛出您可以在全局错误处理程序中处理的任何异常。我已经修改了我的答案,以包含一个自定义授权属性的示例,该属性会引发必要的异常。
    • 新的第 2 部分链接:michaelm.azurewebsites.net/…
    【解决方案2】:

    我认为 AuthorizeAttribute 在遇到未经授权的请求时不会引发任何异常。它只是向客户端发送 401 响应。

    如果您希望发生其他事情,您可以从AuthorizeAttribute 类继承并覆盖HandleUnauthorizedRequest 方法。如果你想抛出一个异常,你可以从那里抛出它。

    public class ThrowingAuthorizeAttribute : AuthorizeAttribute
    {
        protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            throw new HttpException(401, "Unauthorized");
        }
    }
    

    这是 AuthorizeAttribute 源代码的链接,您可以查看它的作用:

    【讨论】:

      猜你喜欢
      • 2022-07-07
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-13
      • 2016-10-31
      • 2011-01-03
      相关资源
      最近更新 更多