您可以从AuthorizeAttribute返回HTTP响应而不会引发异常吗? [英] Can you return an HTTP response from an AuthorizeAttribute without throwing an exception?

查看:119
本文介绍了您可以从AuthorizeAttribute返回HTTP响应而不会引发异常吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using an AuthorizeAttribute on various controllers which may need to return 403 or 429 (too many requests) based on certain attributes of the request itself. I implemented it entirely within a custom OnAuthorization implementation then threw a new HttpResponseException with the appropriate response code if necessary. Worked fine on my machine...

按规模(每分钟有数千个请求),此实现会导致站点崩溃.就性能而言,将相同的逻辑移入控制器动作本身并仅返回适当的HttpResponseMessage可以很好地工作,因此似乎在OnAuthorization中引发异常的开销是性能问题的根本原因.

At scale (many thousands of requests a minute), this implementation sucks to the point where it was crashing the site. Moving the same logic into the controller action itself and just returning an appropriate HttpResponseMessage works beautifully in terms of perf so it seems that the expense of throwing the exception in OnAuthorization is the root cause of the perf issues.

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

I like the idea of implementing this in an attribute I can use to decorate multiple controllers and actions and I vehemently dislike moving even small amounts of logic into controller actions that are then repeated many times. Is it possible to return the appropriate HTTP status from an annotation without throwing an exception? Even if it's not inheriting from AuthorizeAttribute, decorating code in this fashion would be far preferable.

这是Web API 2,不是MVC

This is Web API 2, not MVC

推荐答案

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

As you have discovered, throwing exceptions is expensive. The trick in this case is to override the response in the attribute. As MVC and WebAPI are different (at least prior to MVC6) there are two distinct methods.

设置

Setting the AuthorizationContext.Result allows you to effectively override what action is being performed. Setting this value will prevent the action it is attached to from running at all:

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

WebAPI

非常相似,但是您必须设置 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆