Asp.net WebApi中的自定义授权 - 真是一团糟?

Roy*_*mir 108 asp.net authorization asp.net-web-api

我正在阅读有关WebApi授权的几个资源(书籍和SO答案).

假设我想添加自定义属性,该属性仅允许特定用户访问:

情况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);
   }
  }
}
Run Code Online (Sandbox Code Playgroud)

案例#2

但是我也看到了这个类似的例子,它也覆盖了 OnAuthorization但是要求base:

public override void OnAuthorization(HttpActionContext actionContext) 
{ 
  base.OnAuthorization(actionContext);

    // If not authorized at all, don't bother

    if (actionContext.Response == null)  
     {
      //...
     }
}
Run Code Online (Sandbox Code Playgroud)

然后,检查是否 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
   }
  }
}
Run Code Online (Sandbox Code Playgroud)

案例#4

然后我看到类似的例子,但是调用base.IsAuthorized(context):

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

还有一件事

最后,多米尼克在这里说 :

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

问题

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

  • 2)我base.IsAuthorized or什么时候应该打电话给base.OnAuthorization`?

  • 3)这是他们建造它的方式吗?如果响应为null则一切正常?(案例#2)

NB

请注意,我正在使用(并且想要使用)只有AuthorizeAttribute已经继承的 AuthorizationFilterAttribute

为什么?

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

在此输入图像描述

无论如何我要求通过扩展Authorize属性.

Bad*_*dri 90

我应该使用哪种方法: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;
}
Run Code Online (Sandbox Code Playgroud)

对不起,但不明白你的Q3.BTW,授权过滤器已经存在了很长时间,人们将它用于各种事情,有时甚至是错误的.

还有一件事.最后这里有一个人说:你不应该覆盖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);
    }
}
Run Code Online (Sandbox Code Playgroud)

调用SkipAuthorization是确保AllowAnonymous应用过滤器的部分,即跳过授权.如果重写此方法,则会丢失该行为.实际上,如果您决定将授权建立在用户/角色的基础上,那么您将决定从中获取AuthorizeAttribute.只有正确的选项才能覆盖IsAuthorized而不是已经被覆盖OnAuthorization,尽管技术上可以做到.

PS.在ASP.NET Web API中,还有另一个称为身份验证过滤器的过滤器.想法是您使用它进行身份验证和授权过滤器进行授权,如名称所示.但是,有很多这样的边界被捏造的例子.许多authroization过滤器示例将执行某种身份验证.无论如何,如果你有时间并想要了解更多,请看看这篇MSDN 文章.免责声明:这是我写的.


Tai*_*deh 17

好的,我的建议是假设您使用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);
    
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  3. 现在,在您的控制器中,您可以使用CustomAuthorize属性来使用此授权逻辑来保护您的控制器.


Ane*_*lou 5

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

System.Web.Http.Authorize它几乎解决了因保留和以及其他较旧的身份验证实现而造成的混乱 System.Web.Mvc.Authorize

它提供了操作类型(创建、读取、更新、删除)、资源、角色、声明、视图、自定义需求的非常好的抽象,并允许结合上述任何内容来构建自定义处理程序。此外,这些处理程序也可以组合使用。

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

  • 很高兴知道,但根本没有回答这个问题。 (15认同)