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

Ale*_*akh 41 c# bearer-token asp.net-core asp.net-core-webapi asp.net-core-identity

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

所以我有一个有效且可以解码的令牌,具有所有必需的声明和时间戳.但是一个端点接受它,而另一个端点给我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 
Run Code Online (Sandbox Code Playgroud)

我的验证设置如下:

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;
});
Run Code Online (Sandbox Code Playgroud)

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

怎么可能?

小智 107

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

app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)

来之前

app.UseMvc();
Run Code Online (Sandbox Code Playgroud)

这可能是问题吗?

  • 哦,我的上帝!非常感谢。我花了三个小时来弄清楚为什么我的JWT身份验证不起作用。再次感谢。 (4认同)
  • 我很尴尬地说我错过了 app.UseAuthentication(); 完全! (3认同)
  • 有人可以解释一下为什么顺序很重要吗? (3认同)
  • 杜德就是这样!切换线路X-) (2认同)

jay*_*a_j 20

对于 Dotnetcore 3.1,我放在app.UseAuthentication()之前app.UseAuthorization()

  • 如果我能给这个 1000 票,我会的。如果需要订购这些东西,您会认为会有警告 (3认同)

Kev*_*vin 12

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

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options => ...
Run Code Online (Sandbox Code Playgroud)

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

options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
Run Code Online (Sandbox Code Playgroud)

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

另外你可以添加

options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
Run Code Online (Sandbox Code Playgroud)

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

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

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
Run Code Online (Sandbox Code Playgroud)


Mar*_*ndl 10

对于使用 的任何人.NET Core 3.1,这就是它的工作原理:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseCors("AllowOrigin");
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}
Run Code Online (Sandbox Code Playgroud)


spo*_*ahn 7

我补充说:

app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)

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

参考:Auth 2.0迁移公告