我有一个ASP.NET Core 2.1 Web应用程序项目,该项目使用JWT令牌对项目中内置的Web API进行身份验证。当我在计算机上本地运行它时,它可以很好地工作,但是当我将其部署到Azure(具有相同的环境和应用程序设置)时,它只返回空的HTTP 401响应,以响应来自经过身份验证的客户端的请求,我需要找出原因,可以解决它。
我启用了ASP.NET Core中每个细节的日志记录,但是我从未收到任何有用的输出。
首先,我通过NuGet将Serilog.AspNetCore
和控制台接收器添加到项目中,然后在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();
}
}
但是当我在Azure上运行Web应用程序(使用控制台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 Core Security源代码,发现JwtBearerHandler.HandleAuthenticateAsync
本身并没有做太多日志记录,但是它确实调用了非开源System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler
通常会进行很多日志记录,包括详细的原因(例如(在字符串中带有IDX10209
型错误代码),但我不知道为什么它没有输出我可以捕获的任何内容。
如何记录来自JwtSecurityTokenHandler
的消息?
答案 0 :(得分:1)
我发现了问题:
HttpClient
(正在发送HTTP Authorization
标头不记名令牌)被无意发送到http://
URI,该URI立即收到301重定向到https://
URI。重定向是由IIS执行的,没有涉及ASP.NET Core管道。HttpClient
类不会重新发送Authorization
标头(这是by-design)。
HttpClient
收到的HttpResponseMessage
引用了带有Authorization
标头的原始请求,而不是后标。缺少标题的重定向请求。我必须将Fiddler与HTTPS代理一起使用,以查看第二个请求缺少Authorization
标头。当IdentityServerAuthenticationHandler
或ASP.NET Core自己的JwtBearerHandler
收到不带Authorization
头的请求时,它根本不会调用JwtSecurityTokenHandler
。为此,请在ASP.NET Core Security Git存储库中打开JwtBearerHandler.cs
文件,然后查看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();
}
因此,在我的情况下,它实际上从未调用过JwtSecurityTokenHandler
,因此缺少有关JWT验证的输出消息。
但是我收到的输出消息没有帮助。它们都具有误导性:
因此,最后,解决方法是将原始请求URI的方案从http://
更改为https://
。