您能从AuthorizeAttribute返回HTTP响应而不抛出异常吗?

本文关键字:抛出异常 响应 HTTP AuthorizeAttribute 返回 | 更新日期: 2023-09-27 18:03:08

我在各种控制器上使用AuthorizeAttribute,这些控制器可能需要根据请求本身的某些属性返回403或429(请求太多)。我完全在自定义OnAuthorization实现中实现它,然后抛出一个新的HttpResponseException,并在必要时使用适当的响应代码。在我的机器上运行良好…

在规模上(每分钟数千个请求),这种实现糟糕到导致站点崩溃的地步。将相同的逻辑移动到控制器动作本身,只是返回一个适当的HttpResponseMessage在perf方面工作得很好,所以在OnAuthorization中抛出异常的费用似乎是perf问题的根本原因。

我喜欢在一个属性中实现这个想法,我可以用它来装饰多个控制器和动作,我强烈地不喜欢将少量的逻辑移动到控制器动作中,然后重复多次。是否有可能从注释返回适当的HTTP状态而不抛出异常?即使它没有继承AuthorizeAttribute,以这种方式装饰代码也是可取的。

编辑:这是Web API 2,不是MVC

您能从AuthorizeAttribute返回HTTP响应而不抛出异常吗?

正如您所发现的,抛出异常代价高昂。这种情况下的技巧是覆盖属性中的响应。由于MVC和WebAPI是不同的(至少在MVC6之前),有两种不同的方法。

MVC

设置AuthorizationContext.Result允许您有效地覆盖正在执行的操作。设置此值将阻止它所附加的操作运行:

public override void OnAuthorization(AuthorizationContext filterContext)
{
    if(Throw403)
    {
        filterContext.Result = new HttpStatusCodeResult(403);
    }
}

WebAPI

非常相似,但是您必须设置HttpActionContext.Response属性。这样做的一个方便的特性是,您可以为HTTP状态码获得一个不错的enum:

public override void OnAuthorization(HttpActionContext actionContext)
{
    if(Throw403)
    {
        actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden);
    }
}

如何自定义消息处理程序,您可以在击中控制器之前响应?这发生在管道的早期。

编辑-从网站粘贴相关信息

委派处理程序也可以跳过内部处理程序,直接创建响应:

public class MessageHandler2    :DelegatingHandler
{
 protected override    Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
{
    // Create the response.
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent("Hello!")
    };
    // Note: TaskCompletionSource creates a task that does not contain a delegate.
    var tsc = new TaskCompletionSource<HttpResponseMessage>();
    tsc.SetResult(response);   // Also sets the task state to "RanToCompletion"
    return tsc.Task;
   }
}

这就是如何注册处理程序

  public static class WebApiConfig
    {
  public static void        Register(HttpConfiguration config)
{
    config.MessageHandlers.Add(new MessageHandler1());
    config.MessageHandlers.Add(new MessageHandler2());
    // Other code not shown...
}
}

参考:http://www.asp.net/web-api/overview/advanced/http-message-handlers

不好意思,这是我在移动设备上能做到的最好的