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

ASP.NET Core 6 Web API:JWT无法刷新及请求头传递异常问题

核心问题分析与解决方案

问题根源拆解

  1. API旧JWT残留:你的API仅配置了认证Scheme,但缺失JWT验证参数,导致ASP.NET Core无法正确校验令牌有效性,可能复用旧的认证上下文;同时网站向API发起请求时,未正确传递当前用户的JWT。
  2. 无HttpClient时无法传参/头:直接修改当前请求的HttpContext.Request.Headers只会影响进入网站的请求,不会自动同步到网站向API发起的新请求;MS_HttpRequestMessage仅在HttpClientFactory特定场景下存在,直接读取必然失败。
  3. Cookie传递失效:跨服务场景下Cookie默认受同源策略限制,未配置跨域Cookie规则时无法传递到API。

针对性解决方案

1. 修复API端认证配置(解决旧JWT残留)

API必须配置完整的JWT验证参数,确保能正确解析并校验每个请求的令牌,避免上下文复用:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = jwtOptionsIssuer, // 与网站端保持一致
            ValidAudience = jwtOptionsAudience, // 与网站端保持一致
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptionsKey)), // 与网站端保持一致
            ClockSkew = TimeSpan.FromSeconds(30)
        };
    });

同时确保API的Program.cs中中间件顺序正确:

app.UseRouting();
app.UseAuthentication(); // 必须在UseAuthorization之前
app.UseAuthorization();
app.UseEndpoints(endpoints => { ... });

2. 自动传递当前用户JWT(无需手动处理头)

使用IHttpClientFactory+自定义Handler,自动将当前用户的JWT注入到API请求头:

步骤1:注册自定义DelegatingHandler

public class JwtInjectHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public JwtInjectHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        // 从当前上下文获取JWT(优先从Claim取,其次从请求头取)
        var token = _httpContextAccessor.HttpContext?.User.FindFirst("jwt_token")?.Value 
                    ?? _httpContextAccessor.HttpContext?.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
        
        if (!string.IsNullOrEmpty(token))
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

步骤2:注册HttpClient与Handler

builder.Services.AddHttpContextAccessor();
builder.Services.AddTransient<JwtInjectHandler>();

builder.Services.AddHttpClient("ApiClient", client =>
{
    client.BaseAddress = new Uri("https://your-api-base-url/");
})
.AddHttpMessageHandler<JwtInjectHandler>();

步骤3:调用API时使用命名客户端

private readonly IHttpClientFactory _httpClientFactory;

public YourController(IHttpClientFactory httpClientFactory)
{
    _httpClientFactory = httpClientFactory;
}

public async Task<IActionResult> CallApi()
{
    var client = _httpClientFactory.CreateClient("ApiClient");
    var response = await client.GetAsync("api/users/current");
    // 处理API响应
}

3. 直接传递用户GUID(轻量化方案)

若仅需传递用户标识,可通过自定义头传递:

网站端中间件存储用户ID

public async Task InvokeAsync(HttpContext httpContext)
{
    var userId = httpContext.User.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? string.Empty;
    httpContext.Items["CurrentUserId"] = userId;
    await _next(httpContext);
}

调用API时注入自定义头

var userId = _httpContextAccessor.HttpContext?.Items["CurrentUserId"]?.ToString();
var client = _httpClientFactory.CreateClient("ApiClient");
client.DefaultRequestHeaders.Add("X-User-Id", userId);
var response = await client.GetAsync("api/users/current");

API端获取用户ID

var userId = Request.Headers["X-User-Id"].FirstOrDefault() ?? string.Empty;

4. 解决Cookie跨域传递问题

若必须用Cookie传递,需配置跨域Cookie规则:

网站端设置Cookie

httpContext.Response.Cookies.Append("UserId", userId, new CookieOptions
{
    HttpOnly = true,
    Secure = true, // 仅HTTPS环境启用
    SameSite = SameSiteMode.None,
    Expires = DateTimeOffset.UtcNow.AddHours(1)
});

API端配置CORS允许凭证

builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowWebsite", policy =>
    {
        policy.WithOrigins("https://your-website-url")
              .AllowCredentials()
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});

// Program.cs中启用CORS
app.UseCors("AllowWebsite");

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 18:06:01