一个站点上没有 'Access-Control-Allow-Origin' header,但另一个站点上没有

No 'Access-Control-Allow-Origin' header on one site, but not on another

我们有一个系统,由一个用 ASP.NET/MVC 编写的网站和一个用 ASP.NET/WEBAPI 编写的网络服务站点组成。用户从网站加载页面,使用 JQuery.

调用 Web 服务站点 AJAX

我们正在使用 VS2013 构建它,并使用 MS 的 Web 部署对其进行部署,运行 来自 Jenkins 中配置的作业,因此在 fumble-finger 期间,人们没有太多机会进行某些操作安装。

我们的问题 - 当我们将这两个站点部署到我们的 QA 环境时,一切正常。我们可以访问 Web 服务并加载页面,他们对 Web 服务进行 AJAX 调用,Bob 是你的叔叔。

但是当我们将这两个站点部署到我们的测试环境时,我们得到:

XMLHttpRequest cannot load http://mntest.ktws.XXX.com/api/Motd/getMotdHtml. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mntest.XXX.com' is therefore not allowed access. The response had HTTP status code 404.

奇怪的是 - 网络服务站点的 URL 存储在该网站的 web.config 中。如果我们在测试环境中手动编辑网站的 web.config,并将其指向 QA 环境中的 webservices 站点,一切正常。

我在 QA 和 TEST 的 Web 服务站点的 web.config 上做了一个差异,除了数据库连接字符串中的不同服务器名称外,它们是相同的。我不知道为什么这两个网站的行为不同。

我们已经编写了代码,应该可以处理 CORS 调用。在Global.asax.cs中,我们实现了Application_BeginRequest:

protected void Application_BeginRequest(object sender, EventArgs e)
{
    var origin = HttpContext.Current.Request.Headers["origin"];
    if (origin != null)
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", origin);

    if (HttpContext.Current.Request.HttpMethod == HttpMethod.Options.Method)
    {
        HttpContext.Current.Response.AddHeader("Cache-Control", "no-cache");

        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "DELETE,GET,HEAD,POST,PUT,TRACE");

        // Accept whatever headers they've asked to send us
        var requestedHeaders = HttpContext.Current.Request.Headers["Access-Control-Request-Headers"];
        HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", requestedHeaders);

        HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");

        // This aborts the response, ending any future processing. Which is always a bad idea, except when it isn't.
        // (It seems to be the usual process in dealing with HttpOPTIONS)
        HttpContext.Current.Response.End();
    }
}

当我们在 QA 中对网络服务进行调用时,我们在请求中看到:

GET http://vm-qaweb2.XXX.net/XXX_webservice/api/Motd/getMotdHtml HTTP/1.1
Host: vm-qaweb2.XXX.net
Connection: keep-alive
Cache-Control: max-age=0
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://mntest.XXX.com
authenticationToken: undefined
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36
Referer: http://mntest.XXX.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

在回复中是这样的:

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/7.5
Access-Control-Allow-Origin: http://mntest.XXX.com
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Wed, 17 Jun 2015 21:26:43 GMT
Content-Length: 1064

[The expected content for the message-of-the-day]

在测试中对网络服务进行调用,我们在请求中看到:

OPTIONS http://mntest.ktws.XXX.com/api/Motd/getMotdHtml HTTP/1.1
Host: mntest.ktws.XXX.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: GET
Origin: http://mntest.XXX.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.124 Safari/537.36
Access-Control-Request-Headers: accept, authenticationtoken
Accept: */*
Referer: http://mntest.XXX.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8

我们在响应中看到了这一点:

HTTP/1.1 404 Not Found
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: ASP.NET
Date: Wed, 17 Jun 2015 21:30:58 GMT
Content-Length: 1136
Set-Cookie: NSC_UFTU!L1-WNXFC0-1=ffffffffc3a02c7445525d5f4f58455e445a4a423660;expires=Thu, 18-Jun-2015 05:28:54 GMT;path=/;httponly

[The expected content for the message-of-the-day]

并且在 Chrome 的开发者工具中,我们看到错误:

XMLHttpRequest cannot load http://mntest.ktws.XXX.com/api/Motd/getMotdHtml. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://mntest.XXX.com' is therefore not allowed access. The response had HTTP status code 404.

对于它的价值,getMotdHtml() 控制器:

[HttpGet]
[ActionName("getMotdHtml")]
[AllowAnonymous]
public string getMotdHtml()
{
    try
    {
        string html = "";
        html = this.motdWrangler.getMotdHtml();
        return html;
    }
    catch (Exception ex)
    {
        try
        {
            this.logger.logException(ex, "Exception in getMotdHtml");
        }
        catch
        {
        }
        return "";
    }
}

无论发生什么情况,它都不会返回 404 响应。然而我们得到了一个 404 状态码。尤其令人困惑的是,我们的响应包含预期的 message-of-the-day 文本,只有在执行 getMotdHtml() 操作后才能获得该文本。但如果它有,为什么 404,为什么 Access-Control-Allow-Origin 没有在响应中返回,而 Application_BeginRequest() 必须添加它?

请记住,这不是两个不同的应用程序 - 它是部署到两个不同服务器的相同构建。一方面,它有效,另一方面,它没有,尽管 web.configs 中没有相关差异。

帮忙?

看起来问题可能出在其中一台服务器上安装了 WebDAV:

http://brockallen.com/2012/10/18/cors-iis-and-webdav/

我将这些更改添加到 web.config,我们之前看到的错误消失了。 (当然,我们现在看到了不同的问题,与此无关,但是,这就是编程;)