您能从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正如您所发现的,抛出异常代价高昂。这种情况下的技巧是覆盖属性中的响应。由于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
不好意思,这是我在移动设备上能做到的最好的