简体   繁体   English

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

[英]How to enable CORS via attribute instead of via Application_BeginRequest when preflight is failing

I've been having a CORS configuration issue for over an hour now and I can't find a question that helps me understand this situation. 我一直有一个CORS配置问题超过一个小时了,我找不到一个可以帮助我理解这种情况的问题。

I have an XHR firing on a staging domain with a preflight OPTIONS request that is returning with a 400, and the POST is not being sent because the CORS header to permit it isn't present. 我在暂存域上进行XHR触发,其中预检OPTIONS请求返回400,并且POST没有被发送,因为允许它的CORS头不存在。

I have config.EnableCors(); 我有config.EnableCors(); in my WebApiConfig.cs and am using the NuGet package Microsoft ASP.NET Web API 2.2 Cross-Origin Support ( Microsoft.AspNet.WebApi.Cors v5.23 ) 在我的WebApiConfig.cs使用NuGetMicrosoft ASP.NET Web API 2.2 Cross-Origin SupportMicrosoft.AspNet.WebApi.Cors v5.23

I then set a default instead of using the empty constructor, having seen this question so the WebApiConfig lines are: 然后我设置了一个默认值而不是使用空构造函数,看过这个问题所以WebApiConfig行是:

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

I don't mind this but I'd prefer not setting anything here at all. 我不介意这个,但我不想在这里设置任何东西。 In any case, this isn't working. 无论如何,这是行不通的。

The errors look like this when the OPTIONS request is handled by the Global.asax.cs but doesn't write the header: 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.

The error looks like this when the request isn't handled in the Global.asax.cs : Global.asax.cs未处理请求时,错误看起来像这样:

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

I have been able to access the API cross-domain by using this solution in the Global.asax.cs : 我已经能够通过在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();
        }
    }
}

What I actually want to be doing is this: 我真正想要做的是:

[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)
    {
        ...
    }
}

I can't understand why the CORS attribute isn't handling the preflight request, though I understand why the BeginRequest is. 我无法理解为什么CORS属性不处理预检请求,尽管我理解为什么BeginRequest是。 I want the CORS control to be managed on a controller or action level, not globally. 我希望在控制器或操作级别上管理CORS控件,而不是全局控制。 I thought it might be the HttpPost attribute but removing that didn't work. 我认为它可能是HttpPost属性,但删除它不起作用。

I'm open to the suggestion I have done something wrong or that the request may be being filtered or handled higher up - I'm not certain where to look to address this but I'm not happy to handle CORS globally. 我对我做错了或者请求可能被过滤或处理得更高的建议持开放态度 - 我不确定在哪里寻求解决这个问题,但我不乐意在全球范围内处理CORS。

I'd appreciate any help! 我很感激任何帮助!

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();
    }

}

The code above mentioned worked for me 上面提到的代码对我有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM