首页 文章

ASP.NET Core 2.0 JWT验证因“用户授权失败:(null)”错误而失败

提问于
浏览
24

我正在使用ASP.NET Core 2.0应用程序(Web API)作为JWT发行者来生成移动应用程序的令牌消费品 . 不幸的是,这个令牌无法由一个控制器验证,而另一个控制器可以验证(在同一个asp.net核心2.0应用程序中使用相同的验证设置) .

所以我有一个有效且可以解码的令牌,具有所有必需的声明和时间戳 . 但是一个 endpoints 接受它,而另一个 endpoints 给我401错误和调试输出:

Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:用户授权失败:(null) .

[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: (null).
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[12]
      AuthenticationScheme: Bearer was challenged.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler:Information: AuthenticationScheme: Bearer was challenged.
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
      Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action MyController.Get (WebApi) in 72.105ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 271.077ms 401 
[40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 271.077ms 401

我的验证设置如下:

var secretKey = Configuration["Authentication:OAuth:IssuerSigningKey"];
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));
var tokenValidationParameters = new TokenValidationParameters
{
   ValidateIssuerSigningKey = true,
   IssuerSigningKey = signingKey,
   ValidateIssuer = true,
   ValidIssuer = Configuration["Authentication:OAuth:Issuer"],
   ValidateAudience = true,
   ValidAudience = Configuration["Authentication:OAuth:Audience"],
   ValidateLifetime = true,
   ClockSkew = TimeSpan.Zero,
};

services.AddAuthentication(options =>
{
   options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
   options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.TokenValidationParameters = tokenValidationParameters;
});

这两个 endpoints 是相同的,只存在于不同的控制器中,两者都标有 Authorize 属性 .

怎么可能?

7 回答

  • 2

    configure函数中add语句的顺序非常重要 . 确保这一点

    app.UseAuthentication();
    

    来之前

    app.UseMvc();
    

    这可能是问题吗?

  • 3

    如果添加,在您的startup.cs ConfigureServices方法中

    services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(options => ...
    

    说明:在控制器上使用 [Authorize] 时,它默认绑定到第一个授权系统 .

    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    

    有了这个,您将默认设置为JWT Bearer身份验证 .

    另外你可以添加

    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    

    这一行是如何防止在使用Identity与JWTs时发现404未找到的错误 . 如果您使用身份,DefaultChallengeScheme将尝试将您重定向到登录页面,如果不存在将导致找不到404而不是未经授权的401 . 通过在未经授权的情况下将DefaultChallengeScheme设置为JwtBearerDefaults.AuthenticationScheme,它将不再尝试将您重定向到登录页面

    如果您在 [Authorize] 标记中使用带有JWT身份验证的Cookie身份验证,则可以指定所需的authenticationScheme . 例如

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    
  • 0

    我补充说:

    app.UseAuthentication();
    

    Startup.Configure() 中,我为我解决了这个错误 .

    参考:Auth 2.0 Migration announcement

  • 37

    在startup.cs中尝试这个

    services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(opts => ...
    
  • 6

    这似乎是您未正确验证JWT时收到的行为 . 由于在 Headers 中输入“Bearer:(JWT)”而不是“Bearer(JWT)”,我遇到了这个问题

  • 0

    添加身份验证时,如:

    services.AddAuthentication(options => {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            ....
    

    这意味着放在方法或控制器类之上的每个属性[Authorize]将尝试对默认的身份验证模式(在本例中为JwtBearer) AND IT WILL NOT CASCADE DOWN 进行身份验证,以尝试对可能声明的其他模式进行身份验证(像Cookie架构一样) . 为了使AuthorizeAttribute针对cookie模式进行身份验证,必须将其指定为

    [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
    

    这也可以反过来,即如果cookie模式是默认的,则必须声明JwtBearer模式以授权那些需要JwtBearer令牌认证的方法或控制器

    [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    
  • -2

    您可以尝试这样做:

    .AddJwtBearer(options =>
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true,
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = tokenValidationParameters;
    });'
    

相关问题