我正在阅读有关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);
}
}
}
案例#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;
}
还有一件事
最后,多米尼克说here:
您不应该覆盖OnAuthorization - 因为您将缺少[AllowAnonymous]处理。
问题
1)我应该使用哪种方法:IsAuthorized
或OnAuthorization
? (或何时使用)
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属性。
答案 0 :(得分:89)
我应该使用哪些方法: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;
}
对不起,但不明白你的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);
}
}
对SkipAuthorization
的调用是确保应用AllowAnonymous
过滤器的部分,即跳过授权。如果重写此方法,则会丢失该行为。实际上,如果您决定将授权基于用户/角色,那么您将决定从AuthorizeAttribute
派生。只有正确的选项才能覆盖IsAuthorized
,而不是已经覆盖的OnAuthorization
,尽管技术上可以做到。
PS。在ASP.NET Web API中,还有另一个称为身份验证过滤器的过滤器。想法是您使用它进行身份验证和授权过滤器进行授权,如名称所示。但是,有很多这样的边界被捏造的例子。许多authroization过滤器示例将执行某种身份验证。无论如何,如果你有时间并希望了解更多,请查看此MSDN article。免责声明:这是我写的。
答案 1 :(得分:17)
好的,我的建议是假设您使用OAuth承载令牌来保护您的Web API并且您在发布令牌时将allowedTime设置为用户声明,请执行以下操作。您可以阅读有关token based authentication here
的更多信息覆盖方法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);
}
}
答案 2 :(得分:3)
ASP.NET v5 Introduced a completely new Authorization System. 对于那些打算使用.NET 5的人,我建议进入Microsoft.AspNet.Authorization。
它几乎包含了保持两者造成的混乱
System.Web.Http.Authorize
和System.Web.Mvc.Authorize
以及其他较旧的身份验证实施。
它提供了动作类型(创建,读取,更新,删除),资源,角色,声明,视图,自定义要求的非常好的抽象,并允许构建自定义处理程序,结合上述任何一个。 此外,这些处理程序也可以组合使用。
在ASP.NET v5中,授权现在提供简单的声明性角色和a 更丰富的基于政策的模型,其中表示授权 要求和处理程序评估用户的声明 要求。强制性检查可以基于简单的策略或 评估用户身份和属性的策略 用户试图访问的资源。