【问题标题】:ASP.net same origin policy header doesn't workASP.net 同源策略标头不起作用
【发布时间】:2012-08-11 01:55:52
【问题描述】:

我收到了错误:

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 的请求?感谢您的帮助。

【问题讨论】:

    标签: asp.net iis-7 cross-domain iis-7.5 same-origin-policy


    【解决方案1】:

    我自己做了一些测试,直接使用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,无论我是否从处理程序返回 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. 添加一个header,两个origin空格分隔

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

      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 都接受来自两个来源的处理程序的输出。

    【讨论】:

    • 这是我解决问题的一部分。尽管我使用的代码与此处列出的代码非常相似,但 Chrome 还是抛出了原始问题。我的问题发生是因为我有 both 代码设置 Access-Control-Allow-Origin 标头 在我的网络配置中。一旦我从我的网络配置中删除了该行,我就启动并运行了。
    【解决方案2】:

    您的代码的问题是 Cross Origin 响应标头发送到浏览器 实际请求,而它必须存在 before 实际请求已发出!

    W3 recommends用户代理在提交实际的跨域HTTP请求之前实现预检请求,这意味着要么对包含实际的页面的响应请求或对称为 preflight request 的简单请求的响应(在实际请求之前发出)在发出实际请求时必须包含 Cross Origin 响应标头。

    预检请求返回的

    Cross Origin标头存储在预检结果缓存中。当发出跨域 HTTP 请求时,用户代理会检查 预检结果缓存 中的 Access-Control-Allow-Origin 标头,如果不存在则抛出异常说明:

    无法加载地址,Access-Control-Allow-Origin 不允许来源地址

    当您将Access-Control-Allow-Origin 标头放入web.config 时,从服务器返回的任何响应都包含Access-Control-Allow-Origin 标头,并且浏览器 提交实际的跨域请求。

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

    【讨论】:

      【解决方案3】:

      您能否将您的 web.config 项目包装在一个位置标签中,以便它只针对您的 ashx 位置运行,而不会在其他任何地方运行 - 这会缓解“客观上不是答案”的问题吗?

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

      【讨论】:

        猜你喜欢
        • 2013-10-04
        • 1970-01-01
        • 2014-05-03
        • 2016-12-11
        • 2017-10-05
        • 2017-04-15
        • 2013-03-30
        • 2023-04-07
        • 2016-05-07
        相关资源
        最近更新 更多