Asp.net WebApi中的自定义授权-怎么了?


113

我正在阅读有关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(context):

protected override bool IsAuthorized(HttpActionContext context)
{
 if (something1 && something2 && base.IsAuthorized(context)) //??
 return true;
 return false;
}

还有一件事

最后多米尼克在这里说 :

您不应覆盖OnAuthorization-因为您将缺少[AllowAnonymous]处理。

问题

  • 1)我应该使用哪种方法:IsAuthorizedOnAuthorization?(或何时使用哪个)

  • 2)我base.IsAuthorized or什么时候应该呼叫base.OnAuthorization`?

  • 3)这是他们如何建造的?那如果响应为空,那么一切正常吗?(案例2)

NB

请注意,我仅使用(并且想使用)AuthorizeAttribute已经继承自 AuthorizationFilterAttribute

为什么呢

因为我处在第一阶段:http : //www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

在此处输入图片说明

无论如何我通过扩展Authorize属性询问。


您需要什么来覆盖Authorize属性?您想实现什么用例?如果需要允许某些用户访问,为什么不使用这样的[Authorize(Users =“ Admin”)]属性?
Taiseer Joudeh

1
@TaiseerJoudeh例如,尝试在10:00到12:00之间对用户进行授权(可配置)。您不能使用简单的角色和授权的属性来做到这一点。您必须做出自己的逻辑
Royi Namir 2014年

Answers:


93

我应该使用哪些方法:IsAuthorized或OnAuthorization?(或何时使用哪个)

AuthorizationFilterAttribute如果您的授权逻辑不依赖于已建立的身份和角色,则将进行扩展。对于与用户相关的授权,您将扩展和使用AuthorizeAttribute。对于前一种情况,您将覆盖OnAuthorization。对于后一种情况,您将覆盖IsAuthorized。从这些属性的源代码中可以看到,OnAuthorization如果您从派生,则将其标记为虚拟,以便您覆盖AuthorizationFilterAttribute。另一方面,该IsAuthorized方法在中标记为虚拟AuthorizeAttribute。我相信这是预期用途的良好指针。

我什么时候应该呼叫base.IsAuthorized或base.OnAuthorization?

这个问题的答案在于OO通常如何工作。如果重写方法,则可以完全提供新的实现,也可以使用父级提供的实现并增强行为。例如,以IsAuthorized(HttpActionContext)。基类的行为是对照过滤器中指定的内容与已建立的身份检查用户/角色。说,您想做所有事情,但除此之外,您还想检查其他事情,可能是基于请求标头之类的。在这种情况下,您可以提供这样的替代。

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;
}

很抱歉,但您不了解您的第三季度。顺便说一句,授权过滤器已经存在很长时间了,人们将其用于各种事物,有时甚至会被错误地使用。

还有一件事。最后有人在这里说:您不应该重写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应用过滤器的部分,即跳过授权。如果重写此方法,则会失去该行为。实际上,如果您决定将授权基于用户/角色,则此时您将决定从派生AuthorizeAttribute。此时,仅留给您的正确选项将是覆盖,IsAuthorized而不是已经覆盖的选项OnAuthorization,尽管从技术上讲,这两种方法都是可行的。

PS。在ASP.NET Web API中,还有另一个称为身份验证筛选器的筛选器。想法是,如名称所示,将其用于身份验证,并将授权过滤器用于授权。但是,有很多示例都模糊了此边界。许多认证过滤器示例将进行某种认证。无论如何,如果您有时间并且想了解更多一点,请查看此MSDN 文章。免责声明:它是我写的。


再次感谢,但是如果我在两行之间阅读,IsAuthenticated被OnAuthirization调用,那么为什么不重写OnAuthorization并调用base.OnAuthorization然后检查响应?
罗伊·纳米尔

如果那是您想要的,那么您肯定可以。
Badri 2014年

在我的第三个问题,我的意思是:在运行的基础功能之后- base.OnAuthorization例如,它的唯一的方法来检查,如果它是successful-是考察响应特性?PS的例子是从你的书:-)
Royi纳米尔

是的,据我所知,通常您会寻找401状态代码,但不会为null。顺便说一句,我不记得OnAuthorization在书中写过重写的内容。我确定我不会写有关检查null响应的文章,因为这是我第一次听说它:)
Badri 2014年

是的,我对另一本书感到困惑。我正在同时阅读3本书:securty(用户),实用(用户)和webapi pro(Tugberk's,Zeitler,Ali)。如您所见-他们在那里做过: i.stack.imgur.com/LNGi4.jpg-他们只是检查是否为null,所以我应该检查null或错误代码吗?
罗伊·纳米尔

18

好的,我的建议是假设您使用OAuth承载令牌来保护您的Web API,并且您在设置令牌时将allowedTime设置为对用户的声明,因此建议执行以下操作。您可以在此处阅读有关基于令牌的身份验证的更多信息

  1. 创建从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属性使用此授权逻辑来保护控制器。

1
谢谢。但是我目前正在使用AuthorizeAttribute继承的内容,AuthorizationFilterAttribute并且-在学习方面,我特别询问我应该使用哪种方法以及响应是否具有内容...
Royi Namir 2014年

3

ASP.NET v5引入了全新的授权系统。 对于那些打算使用.NET 5的人,我建议改用Microsoft.AspNet.Authorization。

它几乎包裹了由于保持两者 System.Web.Http.AuthorizeSystem.Web.Mvc.Authorize与其他老的认证实现。

它提供了对动作类型(创建,读取,更新,删除),资源,角色,声明,视图,自定义要求的很好的抽象,并允许结合以上任何一种来构建自定义处理程序。另外,这些处理程序也可以组合使用。

现在,在ASP.NET v5中,授权提供了简单的声明角色,并提供了一个基于策略的更丰富的模型,其中授权在需求中表达,处理程序根据需求评估用户的主张。强制性检查可以基于简单的策略或策略,这些策略或策略可以评估用户身份和用户尝试访问的资源的属性。


14
很高兴知道,但根本无法回答问题。
Zero3 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.