2012-08-14 178 views
4

,我发现了错误:ASP.net同源策略头不起作用

XMLHttpRequest cannot load http://www.scirra.com/handlers/arcadeProcessScore.ashx. Origin http://static1.scirra.net is not allowed by Access-Control-Allow-Origin. 

arcadeProcessScore.ashx我有台词:

public void ProcessRequest (HttpContext context) { 

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://static1.scirra.net"); 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "https://static1.scirra.net"); 
    context.Response.ContentType = "text/plain"; 

然而,错误仍然存​​在。

我也试着简单:

context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); 

这也不起作用。

如果我在web.config级别添加<add name="Access-Control-Allow-Origin" value="*"/>它可行,但显然不是解决方案。

我该如何让arcadeProcessScore.ashx接受static1.scirra.net的请求?谢谢你的帮助。

回答

5

我做一些我自己的测试,直接使用XmlHttpRequest在我的项目进入处理程序。我使用的设置是将应用程序发布到本地IIS(6.1版本,因此可能与7.5的行为有所不同),并让Default.aspx页面调用我的处理程序在Visual Studio中的开发服务器中运行。就像这样:

http://mymachine/WebTest/Default.aspx 

-> XmlHttpRequest get request to 

http://localhost:58025/WebTest/TestHandler.ashx 

代码的处理程序:

public void ProcessRequest (HttpContext context) { 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    context.Response.ContentType = "text/plain"; 
    context.Response.Write("Hello World " + DateTime.Now.ToString()); 
} 

使用IE9时,behviour是一样的,不管我是否没有发送Access-Control-Allow-Origin头球回处理。 IE9发出警告,要求用户确认是否应加载内容。

Chrome(版本21.0.1180.79 m)和FF(版本14.0.1)实际上都会生成对处理程序的请求,并处理处理程序发回的标头。

所以这个曾与Chrome和FF:

context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 

所以这样做:

context.Response.AppendHeader("Access-Control-Allow-Origin", "*"); 

但我一直没能得到任何一方的显示内容,如果我尝试添加同一回应中有几种不同的允许来源。对我来说,没有这些工作:

  1. 添加一些响应头

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine"); 
    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://someothermachine"); 
    
  2. 添加一个标题,用逗号隔开

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine, http://someothermachine"); 
    
  3. 添加一个头的两种来源,二起源空间分开

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine http://someothermachine"); 
    
  4. 添加一个头两个来源空格分隔

    context.Response.AppendHeader("Access-Control-Allow-Origin", "http://mymachine; http://someothermachine"); 
    

为了得到它的工作,我所做的就是遵循this answer给出的建议。然后我的处理程序是这样的:

public void ProcessRequest(HttpContext context) 
{ 
    string[] allowedOrigins = new string[] { "http://mymachine", "http://someothermachine" }; 
    string origin = context.Request.Headers.Get("Origin"); 
    if (allowedOrigins.Contains(origin)) 
     context.Response.AppendHeader("Access-Control-Allow-Origin", origin); 
    context.Response.Cache.SetCacheability(HttpCacheability.NoCache); 
    context.Response.ContentType = "text/plain"; 
    context.Response.Write("Hello World " + DateTime.Now.ToString()); 
} 

有了这个,Chrome和FF接受来自起源处理程序的输出。

+0

工程很好,谢谢! IE限制是可以接受的。 – 2012-08-20 13:51:20

+1

这是我解决我的问题的一部分。尽管我使用的代码非常类似于此处列出的代码,但Chrome仍在抛出原始问题。我的问题发生是因为我的**代码都设置了Access-Control-Allow-Origin头文件**并且** 在我的网络配置。一旦我从我的网页配置中删除了该行,我就开始运行了。 – Garry 2012-12-19 00:53:32

1

您可以将web.config项目包裹在位置标记中,以便它仅在您的ashx位置运行,而且不会在其他地方运行 - 是否会缓解“objviously not the answer”问题?

<location path="~/path/to/handler/arcadeProcessScore.ashx"> 
<httpProtocol> 
    <customHeaders> 
     <clear /> 
     <add name="Access-Control-Allow-Origin" value="http://static1.scirra.net" /> 
    </customHeaders> 
</httpProtocol> 
</location> 
+0

这似乎不起作用,抛出500错误 – 2012-08-20 13:44:32

3

在这里与您的代码的问题是,跨源响应头被发送到浏览器实际要求,而它必须在那里作出的实际要求之前!

W3 recommends用户代理在提交实际上跨源HTTP请求之前实现一个预检要求,这意味着,或者响应于包含实际请求,或以公知的作为一个简单的请求的响应的页面预检请求(在实际请求之前制作)必须包含Cross Origin响应标头,当发出实际请求时。

跨源头从预检要求被存储在预检结果缓存返回。当一个跨源的HTTP请求时,用户代理检查在预检结果缓存Access-Control-Allow-Origin头,如果它不存在抛出一个异常,指出:

can not load address, Origin address is not allowed by Access-Control-Allow-Origin.

当你把Access-Control-Allow-Origin头在web.config中,从服务器返回的任何响应包含Access-Control-Allow-Origin标头,并且浏览器提交实际的跨域请求。

最好的办法是在调用实际的跨域请求之前进行简单的ajax调用(预检请求),并发送该预检请求所需的任何响应头。