您是否可以从AuthorizeAttribute返回HTTP响应而不会抛出异常?

时间:2016-08-20 01:21:22

标签: c# http asp.net-web-api

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

在规模上(每分钟有数千个请求),这个实现很糟糕,它崩溃了网站。将相同的逻辑移动到控制器操作本身并且只返回一个适当的HttpResponseMessage就perf而言非常好用,因此在OnAuthorization中抛出异常的费用似乎是perf问题的根本原因。

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

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

2 个答案:

答案 0 :(得分:17)

正如您所发现的,抛出异常是昂贵的。这种情况下的技巧是覆盖属性中的响应。由于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);
    }
}

答案 1 :(得分:1)

自定义消息处理程序如何在命中控制器之前回复?这种情况发生在管道的早期。

修改 - 粘贴网站上的相关信息

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

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

抱歉格式错误,这是我通过移动设备做的最好的