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

ASP.NET Core 8.0 Web API对接Terminal Four CMS时出现CORS错误

ASP.NET Core 8 Web API 跨域(CORS)问题排查与解决

我搭建了一个ASP.NET Core 8.0 Web API,在Google脚本和手动编写的网站中都能正常运行,但通过内容管理系统Terminal Four调用时,抛出CORS错误:

从源'https://t4.something.edu'获取'https://a.someting.edu/Newsletter/api/newsletter'的请求被CORS策略阻止:对预检请求的响应未通过访问控制检查:不具有HTTP OK状态码。

我只做POST请求,搞不懂为什么在Google脚本和原生网站里没问题,CMS托管的网站就不行?


现有Program.cs代码

var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddCors(options =>
{
    options.AddPolicy(name: MyAllowSpecificOrigins,
                      policy =>
                      {
                          policy.WithOrigins("https://t4.something.edu")
                                .AllowAnyHeader()
                                .AllowAnyMethod();
                      });
});

builder.Services.AddControllers();

// context 
IConfiguration config = new ConfigurationBuilder()
    .AddJsonFile("appsettings.json")
    .AddEnvironmentVariables()
    .AddCommandLine(args)
    .AddUserSecrets<Program>(true)
    .Build();

builder.Services.AddDbContext<NewsletterContext>(option =>
{
    option.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

builder.Services.AddTransient<IApiKeyValidation, ApiKeyValidation>();
builder.Services.AddScoped<ApiKeyAuthFilter>();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseRouting();

app.UseCors(MyAllowSpecificOrigins);

app.UseAuthorization();

app.MapControllers();

app.Run();

Terminal Four中调用脚本

<script>
        function send() 
        {
            var url = 'https://a.something.edu/News/api/news';
            var headers = {
                    'X-API-Key' : "something1234",
                    'Accept': "application/json",
                    'Content-Type': "application/json;charset=utf-8"
            };
            var data = {
                    "email" : document.getElementById("customerEmail").value
            };
            
            var payload = JSON.stringify(data);
            
            var options = {
                method: "POST",
                headers: headers,
                body: payload
            };
            
            try {
                var response = fetch(url, options);
            }catch(error) {
                alert('Error is : ' + error);
            }
            alert('Response is - ' + response);
        }
</script>

已尝试的操作

  • 试过设置mode: "no-cors",但触发415不支持的媒体类型错误
  • Program.cs里已经配置了官方文档中的CORS中间件,问题依旧
  • 目前在Web服务器的web.config里添加了全局响应头:
<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
        </customHeaders>
    </httpProtocol>
</system.webServer>

更新:控制器代码

[Route("api/[controller]")]
[ApiController]
public class NewsletterController(NewsletterContext context) : ControllerBase
{
    private readonly NewsletterContext _context = context;

    [HttpPost]
    public async Task<ActionResult<NewsletterItem>> PostNewsletterItem(NewsletterItem newsletterItem)
    {
       _context.Newsletter_Emails.Add(newsletterItem);

        try
        {
            await _context.SaveChangesAsync();

        }
        catch (DbUpdateConcurrencyException)
        {
           throw;
        }
        return Ok("The record has been saved correctly");
    }
}

更新:模型代码

namespace NewsletterEmails.Models
{
   public class NewsletterItem
   {
       [Key]
       public required string Email { get; set; }
    }
}

问题分析与解决步骤

1. 预检请求失败的核心原因

你的请求包含自定义头X-API-Key,会触发OPTIONS预检请求。当前问题大概率出在以下两点:

  • API密钥验证过滤器拦截了OPTIONS请求:你注册的ApiKeyAuthFilter如果对所有请求(包括OPTIONS)做验证,而OPTIONS请求不会携带X-API-Key,会直接返回非200状态码,导致预检失败
  • 响应头冲突:同时启用ASP.NET Core CORS中间件和IIS自定义头,会导致返回多个Access-Control-Allow-Origin,浏览器拒绝这类响应

2. 针对性修复方案

方案一:修改API密钥过滤器,放行OPTIONS请求

在ApiKeyAuthFilter的OnActionExecuting方法中添加判断:

public override void OnActionExecuting(ActionExecutingContext context)
{
    // 放行OPTIONS预检请求,无需验证API密钥
    if (context.HttpContext.Request.Method == HttpMethod.Options.Method)
    {
        context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
        context.Result = new OkResult();
        return;
    }

    // 原有API密钥验证逻辑...
}

方案二:移除web.config中的全局CORS头

删除web.config里的<add name="Access-Control-Allow-Origin" value="*" />配置,完全由ASP.NET Core中间件处理CORS,避免响应头冲突。

方案三:检查请求路由匹配

前端脚本中的请求URL是https://a.something.edu/News/api/news,但错误信息里的URL是https://a.someting.edu/Newsletter/api/newsletter,确认是否存在拼写错误或路由不匹配——如果OPTIONS请求的路由不存在,会返回404导致预检失败。

方案四:显式指定允许的自定义头

虽然用了AllowAnyHeader(),可以显式指定允许X-API-Key头,避免潜在解析问题:

policy.WithOrigins("https://t4.something.edu")
      .AllowHeaders("X-API-Key", "Content-Type", "Accept")
      .AllowAnyMethod();

3. 验证手段

  • 用Postman发送OPTIONS请求到目标API,查看响应状态码和CORS头是否正确
  • 打开浏览器开发者工具的Network面板,查看OPTIONS请求的具体响应内容,确认是返回401、404还是其他错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 06:54:51