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

ASP.NET Core 3.1 + GraphQL跨域(CORS)异常排查求助

问题原因分析与解决方法

一、为什么调用GraphQL mutation会发送OPTIONS请求?

这是浏览器的**预检请求(Preflight Request)**行为,当你的请求满足以下任意条件时,浏览器会自动先发送OPTIONS请求确认服务器是否允许跨域操作:

  • 请求使用了非简单方法(虽然mutation是POST,但GraphQL通常用application/json作为Content-Type,不属于浏览器定义的"简单POST"范畴)
  • 请求携带了自定义头(比如你设置的Authorization头)
  • 前端设置了credentials: 'include'

OPTIONS预检是浏览器的安全机制,和GraphQL mutation本身的POST请求不冲突,预检通过后才会发送实际的POST mutation请求。

二、后端显示跨域成功但前端仍报错的原因

核心问题是你重复配置了CORS规则导致冲突:

  1. 你同时配置了两种CORS策略:一种是app.UseCors的通配符*允许任意源,另一种是从配置读取指定源的策略
  2. 当使用credentials: 'include'时,浏览器强制要求Access-Control-Allow-Origin必须是具体的源(不能是*),且必须返回Access-Control-Allow-Credentials: true
  3. 后端日志显示的"OPTIONS执行成功"仅指请求返回了200状态码,但实际返回的响应头可能是通配符*,不符合浏览器的CORS安全要求,因此前端报错

三、解决方法

1. 清理重复CORS配置,统一使用指定源策略

删除app.UseCors的通配符配置,仅保留从配置读取指定源的策略,并确保策略正确关联到GraphQL端点:

// Startup.cs - ConfigureServices方法
public void ConfigureServices(IServiceCollection services)
{
    // 读取配置中的允许源
    var allowedOrigins = Configuration.GetSection("RequestOrigins").Get<string[]>();
    
    services.AddCors(options =>
    {
        options.AddPolicy("GraphQLCorsPolicy", policy =>
        {
            policy.WithOrigins(allowedOrigins)
                  .AllowAnyMethod()
                  .AllowAnyHeader()
                  .AllowCredentials(); // 必须开启,对应前端的credentials: 'include'
        });
    });

    // 其他服务配置(GraphQL、MVC等)
    services.AddGraphQL(...);
}

// Startup.cs - Configure方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // 注意中间件顺序:UseCors必须放在UseRouting之后,UseEndpoints/UseGraphQL之前
    app.UseRouting();

    // 指定使用自定义的CORS策略
    app.UseCors("GraphQLCorsPolicy");

    app.UseAuthorization();

    // 注册GraphQL端点
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGraphQL();
    });
    // 如果是用app.UseGraphQL()注册,确保它在UseCors之后
}

2. 验证OPTIONS响应头

用浏览器开发者工具的Network面板查看OPTIONS请求的响应头,确认:

  • Access-Control-Allow-Origin是具体的http://localhost:8889而非*
  • 存在Access-Control-Allow-Credentials: true
  • 存在Access-Control-Allow-Headers: authorization(或包含所有自定义请求头)

3. 前端配置确认

确保ApolloClient的HttpLink配置正确:

const httpLink = new HttpLink({
  uri: '/graphql',
  credentials: 'include',
  headers: {
    'Authorization': `Bearer ${token}`
  }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 16:00:20