一个站点上没有“Access-Control-Allow-Origin”标头,但另一个站点上没有
Posted
技术标签:
【中文标题】一个站点上没有“Access-Control-Allow-Origin”标头,但另一个站点上没有【英文标题】:No 'Access-Control-Allow-Origin' header on one site, but not on another 【发布时间】:2015-09-03 08:48:36 【问题描述】:我们有一个系统,它由一个用 ASP.NET/MVC 编写的网站和一个用 ASP.NET/WEBAPI 编写的 web 服务站点组成。用户从网站加载页面,这些页面使用 JQuery 对 web 服务站点进行 AJAX 调用。
我们使用 VS2013 构建它,并使用 MS 的 Web Deploy 部署它,从 Jenkins 中配置的作业运行,因此在安装过程中没有太多机会让某人摸索一些东西。
我们的问题 - 当我们将这两个站点部署到我们的 QA 环境时,一切正常。我们可以访问 web 服务并加载页面,它们对 web 服务进行 AJAX 调用,而 Bob 是你的叔叔。
但是当我们将这两个站点部署到我们的 TEST 环境时,我们得到:
XMLHttpRequest 无法加载 http://mntest.ktws.XXX.com/api/Motd/getMotdhtml。不 请求中存在“Access-Control-Allow-Origin”标头 资源。原点 'http://mntest.XXX.com' 因此不是 允许访问。响应的 HTTP 状态代码为 404。
奇怪的是,webservices 站点的 URL 存储在网站的 web.config 中。如果我们在测试环境中手动编辑网站的 web.config,并将其指向 QA 环境中的 webservices 站点,则一切正常。
我在 QA 和 TEST 中的 webservices 站点的 web.configs 上做了一个差异,除了数据库连接字符串中的不同服务器名称之外,它们是相同的。我不知道为什么这两个网站的行为不同。
我们已经编写了代码,应该可以处理 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 中调用 web 服务时,我们会在请求中看到:
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]
在 TEST 中对 web 服务进行调用,我们在请求中看到了这一点:
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 无法加载 http://mntest.ktws.XXX.com/api/Motd/getMotdHtml。不 请求中存在“Access-Control-Allow-Origin”标头 资源。原点 'http://mntest.XXX.com' 因此不是 允许访问。响应的 HTTP 状态代码为 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 状态码。特别令人困惑的是,我们的响应包含预期的每日消息文本,它只有在执行 getMotdHtml() 操作时才能获得。但如果有,为什么是 404,为什么没有在响应中返回 Access-Control-Allow-Origin,而 Application_BeginRequest() 必须添加它?
请记住,这不是两个不同的应用程序 - 将相同的构建部署到两个不同的服务器。一方面,它有效,另一方面,它不起作用,尽管 web.configs 中没有相关差异。
帮助?
【问题讨论】:
http://mntest.ktws.XXX.com/
和 http://mntest.XXX.com/
之间有显着差异吗?
也许我应该阅读整个问题
这里的问题是您的 TEST 环境正在发送预检,而您的 QA 环境不是(注意 GET 与 OPTIONS)。有一些事情可能会导致预检,但是,我建议只是让您的后端支持预检请求,而不是阻止它们。
我对 web-api 不够熟悉,无法提供答案,但是,您应该能够从这里的文档中找到答案:asp.net/web-api/overview/security/…
我们并不是要阻止预检。我们想支持他们。我们不知道为什么我们在 QA 中看到预检,但在 TEST 中却没有。也就是说,它是在两种环境中运行的相同代码。 (客户端上的浏览器也一样。)
【参考方案1】:
看起来问题可能是其中一台服务器安装了 WebDAV:
http://brockallen.com/2012/10/18/cors-iis-and-webdav/
我将这些更改添加到 web.config,我们看到的错误就消失了。 (当然,我们现在看到了与此无关的不同问题,但是,这就是编程;)
【讨论】:
以上是关于一个站点上没有“Access-Control-Allow-Origin”标头,但另一个站点上没有的主要内容,如果未能解决你的问题,请参考以下文章
没有 MAMP 的 Mac 上虚拟主机上的 CodeIgniter 站点
Jekyll/Github 站点没有在 Github 上显示正确的示例博客文章
IIS不能启动站点。另一个站点可能在使用您为此站点配置的端口。请为此站点选择一个没有使用的端口。