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

.NET Core 6自定义中间件复刻AllowCredentials()遇POST请求失效问题

问题分析与解决方案

问题根因

你的POST请求失效的核心原因:

  • POST属于非简单请求,浏览器会先发OPTIONS预请求验证跨域权限,这个预请求直接由UseCors中间件处理并返回响应,根本没走到你的自定义中间件,所以预请求响应里没有Access-Control-Allow-Credentials头,浏览器直接拦截了后续的实际POST请求。
  • GET是简单请求,浏览器不会发预请求,直接走到自定义中间件添加了头,所以能正常工作。
  • 你的UseCors中间件顺序错误,放在了UseRouting之前,导致CORS无法正确结合路由信息处理策略。

修复步骤

1. 调整中间件顺序(必须先做)

把UseCors移到UseRouting之后、自定义中间件之前,这是ASP.NET Core CORS中间件的标准位置:

public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    FileLogger.LogInformation("Start Configure");

    if (!env.IsDevelopment())
    {
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseForwardedHeaders();

    FileLogger.LogInformation("Register Routing");
    app.UseRouting();

    // 修正:UseCors移到UseRouting之后
    app.UseCors(allowSpecificOrigins);

    FileLogger.LogInformation("Register Foo Middleware");
    app.UseMiddleware<FooMiddleware1>();
    app.UseMiddleware<FooMiddleware2>();
    app.UseMiddleware<FooMiddleware3>();

    FileLogger.LogInformation("Register Endpoints");
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

2. 动态设置CORS Credentials(替代手动加头)

不要手动添加响应头,而是利用ASP.NET Core的CORS扩展机制动态控制Access-Control-Allow-Credentials,这样能同时覆盖预请求和实际请求:

步骤2.1:创建动态CORS策略提供者
public class DynamicCorsPolicyProvider : ICorsPolicyProvider
{
    private readonly string _targetPolicyName;
    private readonly DefaultCorsPolicyProvider _innerProvider;

    public DynamicCorsPolicyProvider(string targetPolicyName, DefaultCorsPolicyProvider innerProvider)
    {
        _targetPolicyName = targetPolicyName;
        _innerProvider = innerProvider;
    }

    public async Task<CorsPolicy> GetPolicyAsync(HttpContext context, string policyName)
    {
        // 只处理我们定义的目标策略
        if (policyName != _targetPolicyName)
            return await _innerProvider.GetPolicyAsync(context, policyName);

        // 获取基础策略
        var policy = await _innerProvider.GetPolicyAsync(context, policyName);
        
        // 这里替换成你的foo条件判断逻辑
        // 注意:预请求(OPTIONS)没有请求体,所以如果foo依赖请求体,要改用头/查询参数
        bool foo = /* 你的条件判断,比如从context.Request.Headers/Query里取值 */;
        
        // 动态设置是否允许Credentials
        policy.SupportsCredentials = foo;

        return policy;
    }
}
步骤2.2:注册动态提供者并修改CORS策略

在Startup.cs的ConfigureServices里,替换默认的CORS策略提供者,同时不要在基础策略里提前设置AllowCredentials():

// 定义策略名称常量
private const string allowSpecificOrigins = "AllowSpecificOrigins";

services.AddCors(options =>
{
    options.AddPolicy(
        allowSpecificOrigins,
        builder =>
        {
            builder
                .AllowAnyHeader()
                .SetIsOriginAllowed(_ => true)
                .SetPreflightMaxAge(TimeSpan.FromDays(1))
                .WithExposedHeaders("Content-Disposition", "X-Suggested-Filename", "Request-Id")
                .WithMethods(HttpMethod.Get.ToString(), HttpMethod.Post.ToString(), HttpMethod.Options.ToString());
            // 不要加AllowCredentials(),交给动态提供者处理
        });
});

// 替换默认的CORS策略提供者
services.AddSingleton<ICorsPolicyProvider>(sp =>
{
    var innerProvider = sp.GetRequiredService<DefaultCorsPolicyProvider>();
    return new DynamicCorsPolicyProvider(allowSpecificOrigins, innerProvider);
});

额外注意事项

  • 如果你的foo条件依赖请求体,预请求(OPTIONS)是没有请求体的,这时候需要把判断条件转移到请求头或查询参数中,否则预请求会无法正确获取foo值。
  • 前端的withCredentials = true要保持开启,同时确保请求的Origin在CORS策略允许范围内(你的SetIsOriginAllowed(_ => true)已经覆盖了所有Origin)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 01:39:55