自定义授权在 Asp.net WebApi-什么乱七八糟?

我正在阅读一些关于 WebApi 授权的资源(书籍和 SO 答案)。

Suppose I want to add Custom Attribute which allows access only for Certain Users:

Case #1

我见过 overridingOnAuthorization的这种方法,它在出现问题时设置响应

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
public override void OnAuthorization(HttpActionContext actionContext)
{
if ( /*check if user OK or not*/)
{
actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
}
}
}

案例二

但是我也看到了这个类似的例子,它也覆盖了 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是否设置。如果未设置,则意味着请求已被授权,用户是 ok

案例三

但我也看到了这种覆盖 IsAuthorized的方法:

public class AllowOnlyCertainUsers : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext context)
{
if ( /*check if user OK or not*/)
{
return true;// or false
}
}
}

案例四

然后我看到一个类似的例子,但是调用 base.IsAuthorized (上下文) :

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

还有一件事

最后,多米尼克说:

您不应该覆盖 OnAuthorization-因为您将错过[ AllowAnonymous ]处理。

Questions

  • 1)我应该使用哪种方法: IsAuthorized还是 OnAuthorization? (或者什么时候使用哪种方法)

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

  • 3)他们就是这样建造的吗?如果响应为空,那么一切都好吗?(个案 # 2)

注意

请注意,我只使用(并且想使用)从 AuthorizationFilterAttribute继承的 AuthorizeAttribute

Why ?

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

enter image description here

不管怎样,我通过扩展 Authorize 属性询问。

75449 次浏览

好的,我的建议是这样做,假设您使用 OAuth 持有者令牌来保护 Web API,并且在发出令牌时将 allowedTime 设置为用户的索赔。你可以阅读更多关于 这里是基于令牌的认证的资料

  1. 创建从 AuthorizationFilterAttribute 派生的 CustomAuthorizeAttribute
  2. override method OnAuthorizationAsync and use the sample code below:

     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. Now in your controllers you use CustomAuthorize attribute to protect your controllers using this authorization logic.

我应该使用哪种方法: IsAuthorized 还是 OnAuthorization? (或 何时使用哪一个)

如果授权逻辑不依赖于已建立的标识和角色,则扩展 AuthorizationFilterAttribute。对于与用户相关的授权,您将扩展并使用 AuthorizeAttribute。对于前一种情况,您将覆盖 OnAuthorization。对于后一种情况,您将重写 IsAuthorized。正如您可以从这些属性的源代码中看到的,如果从 AuthorizationFilterAttribute派生,则 OnAuthorization被标记为虚拟,以便您重写。另一方面,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;
}

对不起,我不明白你的 Q3。顺便说一句,授权过滤器已经存在很长时间了,人们使用它来做各种事情,有时候也不正确。

One more thing. And finally there was this guy here who said : You 不应该覆盖 OnAuthorization-因为你会失踪 处理。

说这话的人就是访问控制之神 Dominick。显然它是正确的。如果您查看 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,尽管在技术上可以这样做。

附言。在 ASP.NET Web API 中,还有一个名为身份验证过滤器的过滤器。想法是将其用于身份验证和授权过滤器,如名称所示。然而,有很多例子表明这个边界是模糊的。许多授权筛选器示例将执行某种身份验证。无论如何,如果你有时间,想了解更多一点,看看这个 MSDN文章。免责声明: 这是我写的。

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

差不多可以解决两个都留下的麻烦了 System.Web.Http.Authorize and System.Web.Mvc.Authorize and other older authentication implementations.

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

在 ASP.NET v5中,授权现在提供了简单的声明角色和 更丰富的基于策略的模型,其中授权表示为 需求和处理程序评估用户的索赔 必要的检查可以基于简单的政策或 polices which evaluate both the user identity and properties of the 用户试图访问的资源。