预检失败时如何通过属性而不是通过 Application_BeginRequest 启用 CORS

Posted

技术标签:

【中文标题】预检失败时如何通过属性而不是通过 Application_BeginRequest 启用 CORS【英文标题】:How to enable CORS via attribute instead of via Application_BeginRequest when preflight is failing 【发布时间】:2015-10-06 04:57:09 【问题描述】:

我已经有一个多小时的 CORS 配置问题了,我找不到可以帮助我理解这种情况的问题。

我在暂存域上触发了一个 XHR,其中一个预检 OPTIONS 请求返回 400,并且没有发送 POST,因为允许它的 CORS 标头不存在。

我的WebApiConfig.cs 中有config.EnableCors();,并且正在使用NuGetMicrosoft ASP.NET Web API 2.2 Cross-Origin SupportMicrosoft.AspNet.WebApi.Cors v5.23

然后我设置了一个默认值而不是使用空构造函数,因为看到了this 问题,所以WebApiConfig 行是:

var defaultCors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(defaultCors);

我不介意这一点,但我不想在这里设置任何东西。无论如何,这是行不通的。

OPTIONS 请求由Global.asax.cs 处理但不写入标头时,错误如下所示:

OPTIONS http://staging.example.com:8044/Controller/Action
XMLHttpRequest cannot load http://staging.example.com:8044/Controller/Action. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://staging.example.co.uk:8044' is therefore not allowed access.

当请求未在Global.asax.cs 中处理时,错误如下所示:

OPTIONS http://staging.example.com:8044
XMLHttpRequest cannot load http://staging.example.com:8044/Controller/Action. Invalid HTTP status code 400

我已经能够通过在Global.asax.cs 中使用此解决方案来访问 API 跨域:

protected void Application_BeginRequest()

    if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
    
        if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
        
            //These headers are handling the "pre-flight" OPTIONS call sent by the browser
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://staging.example.com:8044");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
            HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Accepts, Content-Type, Origin, X-My-Header");
            HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "60");
            HttpContext.Current.Response.End();
        
    

我真正想做的是:

[EnableCors("http://www.example.com", "*", "get,post")]
public sealed class ControllerController : ApiController

    [EnableCors("http://staging.example.com:8044,http://www.example.com", "*", "post")]
    [HttpPost]
    public async Task<HttpResponseMessage> Action([FromBody] ModelledInput input)
    
        ...
    

我不明白为什么 CORS 属性不处理预检请求,但我明白为什么 BeginRequest 是。我希望在控制器或操作级别上管理 CORS 控件,而不是全局管理。我认为这可能是 HttpPost 属性,但删除它不起作用。

我对我做错了什么或请求可能被过滤或更高层处理的建议持开放态度 - 我不确定从哪里解决这个问题,但我不乐意在全球范围内处理 CORS。

如果有任何帮助,我将不胜感激!

【问题讨论】:

此链接可能对您有所帮助:***.com/questions/7001846/…。在我看来,您必须在服务器端允许 OPTIONS 动词。尝试将 OPTIONS 添加到标题“Access-Control-Allow-Methods”中,就像答案中一样。 【参考方案1】:
protected void Application_BeginRequest()


    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    
        //These headers are handling the "pre-flight" OPTIONS call sent by the browser
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "http://staging.example.com:8044");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Accepts, Content-Type, Origin, X-My-Header");
        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "60");
        HttpContext.Current.Response.End();
    


上面提到的代码对我有用

【讨论】:

但这几乎正是 OP 所说的他们已经做过的事情。这没有任何答案。

以上是关于预检失败时如何通过属性而不是通过 Application_BeginRequest 启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章

CORS 预检神秘地因大猩猩/处理程序而失败

ASP.NET Core 2:使用 [Authorize] 对 API 的 Ajax 调用使预检请求失败

为啥不总是预检 POST 请求?

仅当通过 jQuery 悬停(而不是悬停的行)时,如何向每个表行添加属性?

CORS,防止带有授权标头的请求预检

http跨域预检问题