从 ASP.NET 核心中的不同 HTTP header 读取 JWT 令牌

Read JWT token from different HTTP header in ASP.NET Core

在 ASP.NET 核心 API 项目中,我需要验证位于 header 中不同于授权 header 的另一个 JWT Bearer 令牌。例如,假设发送一个 GET 请求以将产品发送到 /api/products,并在名为 AccessToken.

的 header 中使用不记名令牌
curl --location --request GET 'https://localhost/api/products' \
--header 'AccessToken: <bearer_token>'

我在 API 项目中引用 Microsoft.AspNetCore.Authentication.JwtBearer 包并设置身份验证,如下所示:

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => Configuration.Bind("JwtSettings", options));

但是,我在 JwtBearerOptions Class.

中找不到任何关于 header 名称的信息

如何配置 JWT 身份验证以从名为“AccessToken”的 header 读取 JWT? 甚至可以使用 Microsoft.AspNetCore.Authentication.JwtBearer 包吗?

解决方案似乎是使用 JwtBearerEvents class. In it, there's a delegate property named OnMessageReceived that it's "invoked when a protocol message is first received". The delegate will pass a object of type of MessageReceivedContext, where it has a property named Token that according to the documentation “这将使应用程序有机会从其他位置检索令牌”

创建一个继承自 JwtBearerEvents 的 class,并在 OnMessageReceived 事件中将上下文 object 中的令牌设置为 header“AccessToken”中的值。

/// <summary>
/// Singleton class handler of events related to JWT authentication
/// </summary>
public class AuthEventsHandler : JwtBearerEvents
{
    private const string BearerPrefix = "Bearer ";

    private AuthEventsHandler() => OnMessageReceived = MessageReceivedHandler;

    /// <summary>
    /// Gets single available instance of <see cref="AuthEventsHandler"/>
    /// </summary>
    public static AuthEventsHandler Instance { get; } = new AuthEventsHandler();

    private Task MessageReceivedHandler(MessageReceivedContext context)
    {
        if (context.Request.Headers.TryGetValue("AccessToken", out StringValues headerValue))
        {
            string token = headerValue;
            if (!string.IsNullOrEmpty(token) && token.StartsWith(BearerPrefix))
            {
                token = token.Substring(BearerPrefix.Length);
            }

            context.Token = token;
        }

        return Task.CompletedTask;
    }
}

最后,将事件 class 添加到启动时的 JWT 身份验证 class。

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => 
{
    Configuration.Bind("JwtSettings", options);
    options.Events = AuthEventsHandler.Instance;
});