You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core WebAPI如何实现可选JWT Bearer Token?

ASP.NET Core 可选JWT Bearer Token原生实现方案

ASP.NET Core 原生支持同一个接口可选择携带/不携带JWT访问的场景,不需要手动解析Token,推荐以下两种实现方案:

方案1:全局适配(适合多数接口都需要可选JWT的场景)

首先在Program.cs中配置JWT认证服务,核心是跳过默认的401挑战逻辑,让未携带Token的请求也能正常进入接口:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 常规JWT校验配置,按需调整
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
        // 核心配置:跳过401挑战,不拦截未携带Token的请求
        options.Events = new JwtBearerEvents
        {
            OnChallenge = context =>
            {
                context.HandleResponse();
                return Task.CompletedTask;
            }
        };
    });

// 注册授权服务
builder.Services.AddAuthorization();

// 中间件注册顺序不能错
app.UseAuthentication();
app.UseAuthorization();

在接口中直接通过HttpContext.User判断认证状态即可:

[HttpGet("common/data")]
public IActionResult GetPublicOrPrivateData()
{
    // 已携带有效JWT的逻辑
    if (HttpContext.User.Identity?.IsAuthenticated == true)
    {
        var userId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        var userRole = HttpContext.User.FindFirst(ClaimTypes.Role)?.Value;
        return Ok(new
        {
            Type = "私有内容",
            UserId = userId,
            Role = userRole
        });
    }
    // 未携带JWT的逻辑
    return Ok(new
    {
        Type = "公开内容",
        Data = "未登录用户可见内容"
    });
}

方案2:策略适配(推荐,仅部分接口需要可选JWT的场景)

如果仅少量接口需要可选JWT,其他接口仍需要强制认证,推荐使用自定义授权策略实现,不会影响全局认证逻辑:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 常规JWT校验配置,和上面一致即可
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = builder.Configuration["Jwt:Issuer"],
            ValidAudience = builder.Configuration["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
        };
    });

// 自定义可选JWT的授权策略
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("OptionalJwt", policy =>
    {
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
        // 不要求必须认证通过,只要走完认证流程即可
        policy.RequireAssertion(_ => true);
    });
});

// 中间件注册和上面一致
app.UseAuthentication();
app.UseAuthorization();

需要可选JWT的接口单独标注策略即可,其他需要强制登录的接口仍使用默认[Authorize]特性:

[HttpGet("optional/data")]
[Authorize(Policy = "OptionalJwt")]
public IActionResult GetOptionalData()
{
    // 逻辑和方案1完全一致,通过HttpContext.User判断状态
    if (HttpContext.User.Identity?.IsAuthenticated == true)
    {
        var userId = HttpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        return Ok(new { IsLogin = true, UserId = userId });
    }
    return Ok(new { IsLogin = false, Data = "公开内容" });
}

两种方案都自动完成了JWT的签名校验、过期校验、格式校验,比手动解析Token的安全性和可维护性更高,也完全兼容ASP.NET Core的身份认证体系。

内容的提问来源于stack exchange,提问作者DoubleVoid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 18:36:02