为什么我的身份验证中间件在未提供令牌时将请求传递给授权过滤器



我有一个.NET Core 1.1 Web API,它使用JWT身份验证中间件和自定义授权过滤器。 它们的定义如下:

services.AddSingleton<IAuthorizationRequirement, MercuryEndpointAuthorizationHandler>();
services.AddSingleton<IEndpointAuthorizeDictionary, EndpointRights>();
services.AddSingleton<IAuthorizationHandler, MercuryEndpointAuthorizationHandler>();
services.AddAuthorization(options =>
{
    options.AddPolicy("AuthorizeMercuryEndpoint", policy =>
    {
        policy.AddRequirements(services.BuildServiceProvider().GetService<IAuthorizationRequirement>());
    });
});

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = tokenValidationParameters,
    Events = new JwtBearerEvents()
    {
        OnMessageReceived = async (context) =>
        {
            Debug.WriteLine("====>  JWT Message received");
        },
        OnTokenValidated = async (context) =>
        {
            Debug.WriteLine("====>  JWT token validated");
            context.HttpContext.Items["JwtTokenIsValid"] = true;
        },
        OnAuthenticationFailed = async (context) =>
        {
            Debug.WriteLine("====>  JWT token failed auth");
            context.HttpContext.Items["JwtTokenIsValid"] = false;
            if ((AuthenticationType.IdServer & authTypes) != 0)
                context.SkipToNextMiddleware();
        }
    }
});

当我调用受[Authorize("AuthorizeMercuryEndpoint")]和有效 JWT 令牌保护的终结点时,调用按预期成功,并且我看到进程编写的以下调试:

====>  JWT Message received
====>  JWT token validated
====>  Request authorized (when the auth filter succeeds)

但是,如果我不传递令牌,JWT 中间件似乎会将请求直接传递到授权筛选器,而不尝试身份验证 - 既不调用OnTokenValidated也不调用OnAuthenticationFailed,并且当授权失败时(因为没有经过身份验证的身份),管道将终止。

这是一个问题,因为如果 JWT 令牌验证未通过初始身份验证,我想将请求传递给第二个身份验证中间件。

有谁知道推荐的方法是什么?

JWT 中间件仅在 HTTP 请求中找到令牌时才应用验证部分,如下所示。

Authorize属性现在包含一个 ActiveAuthenticationSchemes 属性,该属性定义将执行哪些身份验证方案以尝试对用户进行身份验证。这样做的好处是,您现在可以删除 JWT 中间件选项中的AutomaticAuthenticate,并且它将在需要时延迟执行 - 例如,如果用户点击不需要身份验证的操作,它将不会执行。

但是,您可能不喜欢的一件事是,MVC 不会在身份验证方案成功后停止,如下所示。如果这是你愿意采取的权衡,我认为这是一个不错的方法。

最新更新