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

ASP.NET Core 5如何处理客户端同一资源重复请求授权头丢失问题

问题原因

你遇到的是老旧.NET Web服务客户端默认的Expect: 100-continue请求逻辑导致的问题:客户端会先发不带Authorization头的预检请求,等待服务端返回100 Continue响应后,才会发送带授权头的完整请求。当前你的服务端在接收到第一个预检请求时,直接触发了认证授权逻辑返回401,客户端因此不会发起第二次带授权的请求。此外你的项目存在路由配置冲突、请求流被提前消耗的潜在问题,也会导致授权头读取异常。

解决方案

1. 修复路由配置冲突

你当前同时开启了端点路由和传统Mvc路由,存在配置冲突,修改ConfigureServices中Mvc的配置:

services.AddMvc(options =>
{
    options.InputFormatters.Insert(0, new RawJsonBodyInputFormatter());
    // 删掉禁用端点路由的配置,和后续UseEndpoints逻辑匹配
    // options.EnableEndpointRouting = false;
})

同时删除Configure方法末尾的app.UseMvc();,避免重复注册路由处理逻辑。

2. 修正日志中间件的请求流处理

如果你的SerilogMiddleware中读取了请求Body内容,必须启用请求缓冲避免流被消耗,示例代码:

public class SerilogMiddleware
{
    private readonly RequestDelegate _next;
    public SerilogMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        // 启用请求缓冲,允许多次读取请求体
        context.Request.EnableBuffering();
        // 原有日志逻辑
        // 读完请求体后重置位置,方便后续中间件读取
        context.Request.Body.Position = 0;
        await _next(context);
    }
}

3. 新增100-continue预检请求处理中间件

在认证授权中间件之前新增中间件,直接响应预检请求,不要走认证流程:

// 放在app.UseAuthentication()之前注册
app.Use(async (context, next) =>
{
    if (context.Request.Headers.TryGetValue("Expect", out var expectValue) 
        && expectValue.ToString().Contains("100-continue", StringComparison.OrdinalIgnoreCase))
    {
        context.Response.StatusCode = StatusCodes.Status100Continue;
        await context.Response.StartAsync();
    }
    await next();
});

4. 修正授权头读取逻辑

你看到的Authorization头值为{}是序列化StringValues结构导致的显示问题,转成字符串即可正常读取:

[ApiExplorerSettings(IgnoreApi = true)]
[HttpPost("Service")]
public IActionResult GetHeader()
{
    // 转成字符串读取,不要直接序列化StringValues对象
    var authValue = HttpContext.Request.Headers["Authorization"].ToString();
    return Ok(authValue);
}

5. 可选:Kestrel配置优化

在Program.cs中配置Kestrel,优化长连接和100-continue处理:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>()
            .ConfigureKestrel(options =>
            {
                // 延长KeepAlive超时适配老旧客户端
                options.Limits.KeepAliveTimeout = TimeSpan.FromMinutes(5);
            });
        });

内容的提问来源于stack exchange,提问作者Franczyk Rafał

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 00:54:05