使用AllowAnonymous属性在WebApi中进行身份验证

时间:2018-05-24 08:50:33

标签: c# asp.net-web-api2

我已通过继承DelegatingHandler并将该类添加为configuration.MessageHandlers.Add(new MyDelegatingHandler())来实施基于JWT的身份验证。

实施DelegatingHandler时,我会覆盖Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)。那里的逻辑很简单 - 我从Authorization标题中检索一个标记,检查它的有效性。如果有效 - 我设置了Thread.CurrentPrincipalHttpContext.Current.User,否则我会返回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标头中提供的令牌无效,则此逻辑将失败。

用户向[AllowAnonymous]的资源发送请求,并在Authorization标头中发送无效令牌,这应该是因为资源允许匿名,但我的代码检查授权,发现令牌是无效并发送HttpStatusCode.Unauthorized

修复方法是检查// TODO: fix用户访问的资源是否允许匿名访问的位置,如果不是,则仅发送HttpStatusCode.Unauthorized,但我无法弄清楚如何正确地做到这一点。

我该怎么做?

1 个答案:

答案 0 :(得分:2)

1。身份验证过滤器

使用引入了Web API 2的Authentication Filters。它们只执行身份验证,但对用户是否有权访问资源却一无所知。正是你需要的。

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 - 即使是具有无效令牌的API。让我们进一步保护它。

2。 AuthorizeAttribute

您需要

AuthorizeAttribute来限制未经身份验证的用户对Web API的访问。您可以使用与上述相同的方法全局应用它:

httpConfig.Filters.Add(new AuthorizeAttribute());

没有有效令牌的人不会通过。好。最后一步是允许具有无效令牌的用户访问某些特定资源。

3。 AllowAnonymousAttribute

从现在开始,AllowAnonymousAttribute应该可行。基本上AuthorizeAttribute只检查资源是否由[AllowAnonymous]标记,并在此情况下跳过授权。

结论

通常,Web API受未经身份验证的用户保护,但某些资源可以通过应用[AllowAnonymous]来禁用授权。 JwtAuthenticationFilter我们在任何情况下都实现了以上工作,因此具有有效令牌的用户将始终进行身份验证 - 即使资源允许匿名访问。