在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)我应该使用哪些方法: OnAuthorizationOnAuthorization ? (或何时使用哪个)

  • 2)什么时候应该调用base.IsAuthorized or base.OnAuthorization`?

  • 3)他们是如何build立的? 如果答复是空的,那么一切都好? (情况#2)

NB

请注意,我正在使用(和要使用)只有AuthorizeAttribute已经从AuthorizationFilterAttributeinheritance

为什么?

因为我在第一阶段: 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的调用是确保应用AllowAnonymousfilter的部分,也就是说,跳过了授权。 如果您重写此方法,则会丢失该行为。 实际上,如果您决定将您的授权基于用户/angular色,那么您将决定从AuthorizeAttribute派生。 在这一点上只有正确的选项将覆盖OnAuthorization而不是已经重写的OnAuthorization ,虽然在技术上可以做到。

PS。 在ASP.NET Web API中,还有另一个称为authenticationfilter的filter。 想法是,你使用它的authentication和授权filter的授权,如名称所示。 然而,这个界限被模糊了很多例子。 许多authroizationfilter的例子会做一些authentication。 无论如何,如果您有时间并且想要了解更多信息,请参阅此MSDN 文章 。 免责声明:这是我写的。

好吧,我的build议是,假设您使用OAuth承载标记来保护您的Web API,并且您在颁发令牌时将allowedTime设置为用户的声明,则执行以下操作。 您可以在这里阅读更多关于基于令牌的authentication

  1. 创build派生自AuthorizationFilterAttribute的CustomAuthorizeAttribute
  2. 重写方法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); } } 
  3. 现在在您的控制器中使用CustomAuthorize属性来保护您的控制器使用这个授权逻辑。

ASP.NET v5引入了一个全新的授权系统。 对于那些将要使用.NET 5的人,我build议进入Microsoft.AspNet.Authorization。

保存了System.Web.Http.AuthorizeSystem.Web.Mvc.Authorize以及其他较早的authentication实现所导致的混乱。

它提供了一个非常好的动作types(创build,读取,更新,删除),资源,angular色,索赔,视图,自定义需求的抽象,并允许构build自定义处理程序,结合上述任何。 另外这些处理程序也可以组合使用。

在ASP.NET v5中,授权现在提供简单的声明式angular色和更丰富的基于策略的模型,其中授权在需求和处理程序中表示,评估用户对需求的声明。 命令性检查可以基于简单的策略或策略,这些策略或策略评估用户正试图访问的资源的用户身份和属性。