代码之家  ›  专栏  ›  技术社区  ›  Dai

如何从JwtSecurityTokenHandler获取日志输出?

  •  2
  • Dai  · 技术社区  · 6 年前

    我有一个ASP.NET Core 2.1 Web应用程序项目,它使用JWT令牌对项目内置的Web API进行身份验证。当我在我的机器上本地运行它时,它工作得很好,但是当我将它部署到Azure(使用相同的环境和应用程序设置)时,它只会返回空的http401响应,以响应来自经过身份验证的客户端的请求,我需要找出原因以便修复它。

    我在ASP.NET内核中启用了对每个细节的日志记录,但是我从未收到任何有用的输出。

    首先,我补充道 Serilog.AspNetCore 控制台通过NuGet接收到项目,然后在 Verbose 水平 Program.cs :

    public class Program
    {
        public static void Main(string[] args)
        {
            Log.Logger = new LoggerConfiguration()
                .MinimumLevel.Verbose()
                .MinimumLevel.Override("Microsoft", LogEventLevel.Verbose)
                .MinimumLevel.Override("System", LogEventLevel.Verbose)
                .MinimumLevel.Override("Microsoft.AspNetCore.Authentication", LogEventLevel.Verbose)
                .Enrich.FromLogContext()
                .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {SourceContext}{NewLine}{Message:lj}{NewLine}{Exception}{NewLine}", theme: AnsiConsoleTheme.Literate)
                .CreateLogger();
    
            CreateWebHostBuilder( args ).Build().Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(String[] args)
        {
            return WebHost.CreateDefaultBuilder( args )
                .ConfigureLogging( (ctx, cfg ) =>
                {
                    cfg.ClearProviders();
                } )
                .UseStartup<Startup>()
                .UseSerilog();
        }
    }
    

    stdout 登录到文件)我得到以下输出:

    [04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
    Authorization Filter: Before executing OnAuthorizationAsync on filter 
    Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.
    
    [04:13:10 Verbose] 
    IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
    HandleAuthenticateAsync called
    
    [04:13:10 Debug] 
    IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
    AuthenticationScheme: Bearer was not authenticated.
    
    [04:13:10 Information] 
    Microsoft.AspNetCore.Authorization.DefaultAuthorizationService
    Authorization failed.
    
    [04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
    Authorization Filter: After executing OnAuthorizationAsync on filter 
    Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter.
    
    [04:13:10 Information] 
    Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
    Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
    
    [04:13:10 Verbose] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker
    Before executing action result Microsoft.AspNetCore.Mvc.ChallengeResult.
    
    [04:13:10 Information] Microsoft.AspNetCore.Mvc.ChallengeResult
    Executing ChallengeResult with authentication schemes (["Bearer"]).
    
    [04:13:10 Verbose] 
    IdentityServer4.AccessTokenValidation.IdentityServerAuthenticationHandler
    Forwarding challenge to scheme: BearerIdentityServerAuthenticationJwt
    

    请注意,尽管日志记录很详细,但错误消息(下面重复)并没有给出任何解释:

    AuthenticationScheme: Bearer was not authenticated.
    Authorization failed.
    

    我翻遍了ASP.NET核心安全源代码来看看 JwtBearerHandler.HandleAuthenticateAsync System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler 它通常会进行大量的日志记录,包括详细的原因(例如 IDX10209 -在字符串中键入错误代码),但我不知道为什么它不输出任何我可以捕获的内容。

    如何记录来自的消息 JwtSecurityTokenHandler ?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Dai    6 年前

    我发现了问题:

    • HttpClient (发送HTTP Authorization 标头承载令牌)是 把它送到医院 http:// 立即收到301重定向到 https:// URI。重定向是由IIS执行的,没有涉及ASP.NET核心管道。
    • 这个 类不重新发送 授权 by-design
      • 我从来没有注意到这一点,因为我的 HttpClient客户端 HttpResponseMessage 提到了 起初的 授权 header,而不是缺少header的post重定向请求。我不得不使用Fiddler和HTTPS代理来查看第二个请求是否缺少 授权 标题。
    • IdentityServerAuthenticationHandler 或者ASP.NET内核自己的 JwtBearerHandler 授权 JwtSecurityTokenHandler 完全。要看到这个,打开 JwtBearerHandler.cs 文件中的ASP.NET核心安全Git repo并查看 HandleAuthenticateAsync :它有以下逻辑:

      if (string.IsNullOrEmpty(token))
      {
          string authorization = Request.Headers["Authorization"];
      
          // If no authorization header found, nothing to process further
          if (string.IsNullOrEmpty(authorization))
          {
              return AuthenticateResult.NoResult();
          }
      
    • 所以在我的情况下,它从来没有打过电话 因此,缺少关于JWT验证的输出消息。

    • 但是,我收到的输出消息没有帮助。它们都是误导性的:

      • “AuthenticationScheme:承载未通过身份验证。”应该类似于“AuthenticationScheme:请求中不存在承载令牌。”而是。
      • “授权失败。”应该是“由于请求中不存在令牌而跳过授权”
    • 因此,最终的解决方案是将原始请求URI的方案从 https地址://