我有一个 .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 token 保护的端点时,调用按预期成功,并且我看到该进程编写的以下调试:
====> JWT Message received
====> JWT token validated
====> Request authorized (when the auth filter succeeds)
但是,如果我不传递 token ,JWT 中间件似乎会直接将请求传递到授权过滤器而不尝试身份验证 - OnTokenValidated
和 OnAuthenticationFailed
都不会被调用,当授权失败时(因为没有经过身份验证的身份)管道将终止。
这是一个问题,因为如果 JWT token 验证未通过初始身份验证,我想将请求传递给第二个身份验证中间件。
有人知道推荐的方法是什么吗?
最佳答案
JWT 中间件仅在 HTTP 请求中找到 token 时才应用验证部分,就像您可以的 see here .
Authorize 属性现在包含一个 ActiveAuthenticationSchemes 属性,该属性定义将执行哪些身份验证方案来尝试对用户进行身份验证。这样做的好处是,您现在可以删除 JWT 中间件选项中的 AutomaticAuthenticate
,并且它将在需要时延迟执行 - 例如,如果用户点击不需要身份验证的操作,它将执行不执行。
但是,您可能不喜欢的一件事是,在身份验证方案成功后,MVC 不会像您一样停止 see here 。如果这是您愿意做出的权衡,我认为这是一个很好的方法。
关于authentication - 为什么我的身份验证中间件在未提供 token 的情况下将请求传递给授权过滤器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41701316/