在Asp.net WebApi自定义授权 – 什么混乱?
我正在从WebApi的许多资源(书籍和答案)阅读授权。
假设我想添加自定义属性,只允许某些用户访问:
情况1
我已经看到这种重写 OnAuthorization
方法,如果出现错误,它会设置响应
public class AllowOnlyCertainUsers : AuthorizeAttribute { public override void OnAuthorization(HttpActionContext actionContext) { if ( /*check if user OK or not*/) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); } } }
案例#2
但是我也看到了这个类似的例子,它也覆盖OnAuthorization
但调用base
:
public override void OnAuthorization(HttpActionContext actionContext) { base.OnAuthorization(actionContext); // If not authorized at all, don't bother if (actionContext.Response == null) { //... } }
然后,检查HttpActionContext.Response
是否设置。 如果没有设置,则表示请求已被授权,用户正常
案例#3
但我也看到这种重写IsAuthorized
:
public class AllowOnlyCertainUsers : AuthorizeAttribute { protected override bool IsAuthorized(HttpActionContext context) { if ( /*check if user OK or not*/) { return true;// or false } } }
案例#4
然后我看到类似的例子,但调用base.IsAuthorized(上下文):
protected override bool IsAuthorized(HttpActionContext context) { if (something1 && something2 && base.IsAuthorized(context)) //?? return true; return false; }
还有一件事
多米尼克最后在这里说:
您不应该重写OnAuthorization – 因为您将缺less[AllowAnonymous]处理。
问题
-
1)我应该使用哪些方法:
OnAuthorization
或OnAuthorization
? (或何时使用哪个) -
2)什么时候应该调用
base.IsAuthorized or
base.OnAuthorization`? -
3)他们是如何build立的? 如果答复是空的,那么一切都好? (情况#2)
NB
请注意,我正在使用(和要使用)只有AuthorizeAttribute
已经从AuthorizationFilterAttribute
inheritance
为什么?
因为我在第一阶段: http : //www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api
无论如何,我通过扩展授权属性问。
我应该使用哪些方法:IsAuthorized或OnAuthorization? (或何时使用哪个)
如果您的授权逻辑不依赖于build立的身份和angular色,那么您将扩展AuthorizationFilterAttribute
。 对于用户相关的授权,您将扩展并使用AuthorizeAttribute
。 对于前一种情况,您将覆盖OnAuthorization
。 对于后者,您将覆盖IsAuthorized
。 正如你从这些属性的源代码中可以看到的,如果你从AuthorizationFilterAttribute
派生的话, OnAuthorization
被标记为虚拟的。 另一方面, IsAuthorized
方法在AuthorizeAttribute
被标记为虚拟的。 我相信这是一个很好的指示用途。
什么时候应该调用base.IsAuthorized或base.OnAuthorization?
这个问题的答案在于OO如何运作。 如果你重写一个方法,你可以完全提供一个新的实现,也可以回顾父级提供的实现,并增强行为。 例如,采取IsAuthorized(HttpActionContext)
。 基类行为是根据filter中指定的内容与build立的标识来检查用户/angular色。 说,你想做的除此之外,你想检查的东西,可能是基于请求头或东西。 在这种情况下,你可以提供这样的覆盖。
protected override bool IsAuthorized(HttpActionContext actionContext) { bool isAuthroized = base.IsAuthorized(actionContext); // Here you look at the header and do your additional stuff based on actionContext // and store the result in isRequestHeaderOk // Then, you can combine the results // return isAuthorized && isRequestHeaderOk; }
我很抱歉,但不明白你的Q3。 顺便说一句,授权filter已经存在很长时间了,人们会将它用于各种事情,有时也会出现错误。
还有一件事。 最后这里有个人说:你不应该重写OnAuthorization – 因为你会错过[AllowAnonymous]处理。
那个说那是门禁的神 – 多米尼克。 显然这是对的。 如果你看一下OnAuthorization
的实现(复制如下)
public override void OnAuthorization(HttpActionContext actionContext) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } if (SkipAuthorization(actionContext)) { return; } if (!IsAuthorized(actionContext)) { HandleUnauthorizedRequest(actionContext); } }
对SkipAuthorization
的调用是确保应用AllowAnonymous
filter的部分,也就是说,跳过了授权。 如果您重写此方法,则会丢失该行为。 实际上,如果您决定将您的授权基于用户/angular色,那么您将决定从AuthorizeAttribute
派生。 在这一点上只有正确的选项将覆盖OnAuthorization
而不是已经重写的OnAuthorization
,虽然在技术上可以做到。
PS。 在ASP.NET Web API中,还有另一个称为authenticationfilter的filter。 想法是,你使用它的authentication和授权filter的授权,如名称所示。 然而,这个界限被模糊了很多例子。 许多authroizationfilter的例子会做一些authentication。 无论如何,如果您有时间并且想要了解更多信息,请参阅此MSDN 文章 。 免责声明:这是我写的。
好吧,我的build议是,假设您使用OAuth承载标记来保护您的Web API,并且您在颁发令牌时将allowedTime设置为用户的声明,则执行以下操作。 您可以在这里阅读更多关于基于令牌的authentication
- 创build派生自AuthorizationFilterAttribute的CustomAuthorizeAttribute
-
重写方法
OnAuthorizationAsync
并使用下面的示例代码:public class CustomAuthorizeAttribute : AuthorizationFilterAttribute { public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) { var principal = actionContext.RequestContext.Principal as ClaimsPrincipal; if (!principal.Identity.IsAuthenticated) { return Task.FromResult<object>(null); } var userName = principal.FindFirst(ClaimTypes.Name).Value; var userAllowedTime = principal.FindFirst("userAllowedTime").Value; if (currentTime != userAllowedTime) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla"); return Task.FromResult<object>(null); } //User is Authorized, complete execution return Task.FromResult<object>(null); } }
- 现在在您的控制器中使用CustomAuthorize属性来保护您的控制器使用这个授权逻辑。
ASP.NET v5引入了一个全新的授权系统。 对于那些将要使用.NET 5的人,我build议进入Microsoft.AspNet.Authorization。
保存了System.Web.Http.Authorize
和System.Web.Mvc.Authorize
以及其他较早的authentication实现所导致的混乱。
它提供了一个非常好的动作types(创build,读取,更新,删除),资源,angular色,索赔,视图,自定义需求的抽象,并允许构build自定义处理程序,结合上述任何。 另外这些处理程序也可以组合使用。
在ASP.NET v5中,授权现在提供简单的声明式angular色和更丰富的基于策略的模型,其中授权在需求和处理程序中表示,评估用户对需求的声明。 命令性检查可以基于简单的策略或策略,这些策略或策略评估用户正试图访问的资源的用户身份和属性。