使用 AllowAnonymous 属性在 Web Api 中进行身份验证
Authentication in WebApi with AllowAnonymous attribute
我通过继承 DelegatingHandler
并将 class 添加为 configuration.MessageHandlers.Add(new MyDelegatingHandler())
实现了 JWT-based 身份验证。
在实现 DelegatingHandler
时,我覆盖了 Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
。那里的逻辑很简单——我从 Authorization
header 中检索了一个令牌,检查它的有效性。如果有效 - 我设置 Thread.CurrentPrincipal
和 HttpContext.Current.User
,否则我 return new HttpResponseMessage(HttpStatusCode.Unauthorized)
基本上是这样的(非常简化):
public class TokenValidationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var token = GetTokenFromAuthorizeHeader(request);
if (TokenIsValid(token)) {
var principal = CreatePrincipal(token);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return base.SendAsync(request, cancellationToken);
} else {
// TODO: fix
return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
}
}
现在即使在具有 [AllowAnonymous]
属性的 WebApi 方法上也会调用此方法。这很好,因为即使该方法允许匿名,我也想设置主体。但如果 Authorization
header 中提供的令牌无效,则此逻辑失败。
用户使用 [AllowAnonymous]
和 Authorization
header 中的无效令牌向资源发送请求,应该通过,因为资源允许匿名,但我的代码检查授权,发现token无效,发送HttpStatusCode.Unauthorized
.
修复方法是检查 // TODO: fix
是用户正在访问的资源是否允许匿名,如果不允许则只发送 HttpStatusCode.Unauthorized
,但我无法弄清楚如何正确执行此操作。
我该怎么做?
1。身份验证过滤器
使用Authentication Filters,其中Web API 2介绍。它们只执行 身份验证 ,但不会说明用户是否有权访问资源。正是您所需要的。
public class JwtAuthenticationFilter : IAuthenticationFilter
{
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var token = GetTokenFromAuthorizeHeader(context.Request);
if (TokenIsValid(token)) {
var principal = CreatePrincipal(token);
// Use context.Principal instead of Thread.CurrentPrincipal
// and HttpContext.Current.User whenever.
context.Principal = principal;
}
return Task.CompletedTask;
}
// TODO: Implement remaining IAuthencitaionFilter members.
}
全局应用此 JwtAuthenticationFilter
以对所有请求执行身份验证:
// httpConfig is an instance of HttpConfiguration
httpConfig.Filters.Add(new JwtAuthenticationFilter());
通过这种方式,如果令牌正常,用户就可以通过身份验证。但仍然所有用户都可以访问您的 API - 即使是那些使用无效令牌的用户。让我们更进一步,保护它。
2。授权属性
AuthorizeAttribute 是您需要限制未经身份验证的用户访问 Web API 的内容。您可以使用与上述相同的方法在全球范围内应用它:
httpConfig.Filters.Add(new AuthorizeAttribute());
没有有效token者不予通过。好的。最后一步是允许使用无效令牌的用户访问某些特定资源。
3。允许匿名属性
从现在开始 AllowAnonymousAttribute
应该可以了。基本上 AuthorizeAttribute
只是检查资源是否被 [AllowAnonymous]
标记并在这种情况下跳过授权。
结论
一般来说,Web API 受到保护,不受未经身份验证的用户的影响,但某些资源可以通过应用 [AllowAnonymous]
来禁用授权。 JwtAuthenticationFilter
我们上面实现的在任何情况下都有效,因此拥有有效令牌的用户将始终通过身份验证 - 即使资源允许匿名访问。
我通过继承 DelegatingHandler
并将 class 添加为 configuration.MessageHandlers.Add(new MyDelegatingHandler())
实现了 JWT-based 身份验证。
在实现 DelegatingHandler
时,我覆盖了 Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
。那里的逻辑很简单——我从 Authorization
header 中检索了一个令牌,检查它的有效性。如果有效 - 我设置 Thread.CurrentPrincipal
和 HttpContext.Current.User
,否则我 return new HttpResponseMessage(HttpStatusCode.Unauthorized)
基本上是这样的(非常简化):
public class TokenValidationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var token = GetTokenFromAuthorizeHeader(request);
if (TokenIsValid(token)) {
var principal = CreatePrincipal(token);
Thread.CurrentPrincipal = principal;
HttpContext.Current.User = principal;
return base.SendAsync(request, cancellationToken);
} else {
// TODO: fix
return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(HttpStatusCode.Unauthorized));
}
}
}
现在即使在具有 [AllowAnonymous]
属性的 WebApi 方法上也会调用此方法。这很好,因为即使该方法允许匿名,我也想设置主体。但如果 Authorization
header 中提供的令牌无效,则此逻辑失败。
用户使用 [AllowAnonymous]
和 Authorization
header 中的无效令牌向资源发送请求,应该通过,因为资源允许匿名,但我的代码检查授权,发现token无效,发送HttpStatusCode.Unauthorized
.
修复方法是检查 // TODO: fix
是用户正在访问的资源是否允许匿名,如果不允许则只发送 HttpStatusCode.Unauthorized
,但我无法弄清楚如何正确执行此操作。
我该怎么做?
1。身份验证过滤器
使用Authentication Filters,其中Web API 2介绍。它们只执行 身份验证 ,但不会说明用户是否有权访问资源。正是您所需要的。
public class JwtAuthenticationFilter : IAuthenticationFilter
{
public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
{
var token = GetTokenFromAuthorizeHeader(context.Request);
if (TokenIsValid(token)) {
var principal = CreatePrincipal(token);
// Use context.Principal instead of Thread.CurrentPrincipal
// and HttpContext.Current.User whenever.
context.Principal = principal;
}
return Task.CompletedTask;
}
// TODO: Implement remaining IAuthencitaionFilter members.
}
全局应用此 JwtAuthenticationFilter
以对所有请求执行身份验证:
// httpConfig is an instance of HttpConfiguration
httpConfig.Filters.Add(new JwtAuthenticationFilter());
通过这种方式,如果令牌正常,用户就可以通过身份验证。但仍然所有用户都可以访问您的 API - 即使是那些使用无效令牌的用户。让我们更进一步,保护它。
2。授权属性
AuthorizeAttribute 是您需要限制未经身份验证的用户访问 Web API 的内容。您可以使用与上述相同的方法在全球范围内应用它:
httpConfig.Filters.Add(new AuthorizeAttribute());
没有有效token者不予通过。好的。最后一步是允许使用无效令牌的用户访问某些特定资源。
3。允许匿名属性
从现在开始 AllowAnonymousAttribute
应该可以了。基本上 AuthorizeAttribute
只是检查资源是否被 [AllowAnonymous]
标记并在这种情况下跳过授权。
结论
一般来说,Web API 受到保护,不受未经身份验证的用户的影响,但某些资源可以通过应用 [AllowAnonymous]
来禁用授权。 JwtAuthenticationFilter
我们上面实现的在任何情况下都有效,因此拥有有效令牌的用户将始终通过身份验证 - 即使资源允许匿名访问。