Header 没有为 OPTIONS Ajax 请求设置

Header not being set for OPTIONS Ajax request

我有一个 ascx 页面 GetToken.ashx

public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "text/plain";
    context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
    context.Response.Write(Token.CreateToken());
}

当我AJAX到这个页面时,它returns以下header:

Request Method:GET
Status Code:200 OK
Access-Control-Allow-Origin:*
Cache-Control:private
Content-Length:36
Content-Type:text/plain; charset=utf-8
Date:Tue, 14 Apr 2015 17:20:53 GMT
Server:Microsoft-IIS/8.5
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET

当发出 AJAX 请求的页面被放置在沙盒 iFrame 中时,它显示错误:

XMLHttpRequest cannot load https://127.0.0.1:112/handlers/gettoken.ashx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

和returns headers:

Request Method:OPTIONS
Status Code:200 OK
Allow:OPTIONS, TRACE, GET, HEAD, POST
Content-Length:0
Date:Tue, 14 Apr 2015 17:30:14 GMT
Public:OPTIONS, TRACE, GET, HEAD, POST
Server:Microsoft-IIS/8.5
X-Powered-By:ASP.NET

我似乎无法获得添加 header 的 OPTIONS 请求。将 allow-same-origin 添加到沙盒属性会将请求更改为 GET,但我不想授予 iFrame 这些权限。

确保您的 IIS 设置允许 OPTION 到该处理程序 - 部署到具有应用程序池名称 "web-app" 的应用程序并且相应的处理程序映射应该允许 OPTION 请求。

以下是执行此操作的步骤。

  • select 需要应用程序池
  • 单击处理程序映射
  • select *.ashx 并双击相应的处理程序,单击 Request Restriction ,看看那里是否有选项动词,如果没有,请添加。

上面提到这里 - http://www.chrisweldon.net/blog/2012/04/13/jquery-file-uploader/

您可能需要使用以下代码。

public void ProcessRequest (HttpContext context) {
    context.Response.ContentType = "text/plain";
    context.Response.AddHeader("Access-Control-Allow-Origin", "*");
    // You can try adding requested origin here instead of * like this - Request.Headers["Origin"] or only the specific domain, in your case it is -https://127.0.0.1:112
    if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
    {
        context.Response.AddHeader("Access-Control-Allow-Methods", "POST, PUT, DELETE");
        context.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
        context.Response.AddHeader("Access-Control-Max-Age", "1728000");
    }
    context.Response.Write(Token.CreateToken());
}

我已经在 my blog 中解释过了。这是针对 WCF 的,但它也应该适用于您的情况!您可能需要将 * for allowed origin 更改为 requested origin,因为 * 存在安全问题,它允许所有域进行 CORS 调用。

您能否尝试在 您的 HTML 和 iFrame 页面(在 HTML DOC 中)添加以下代码并检查它是否有效?

<script>document.domain = 'myDomain.com'</script>

注意:请将 'myDomain' 替换为您正在使用的域的适当域名(来源)

如果没有 allow-same-origin 选项,从沙盒 iframe 发出 AJAX 请求似乎是绝对不可能的。

查看此答案以获得详细解释:IFRAME sandbox attribute is blocking AJAX calls

不过,我不太相信。在放弃之前,请确保您的服务器接受 AJAX 来自不同主机名的请求而无需沙盒(即,如果它支持 CORS)。

有关 CORS 的更多信息,请参阅:http://www.html5rocks.com/en/tutorials/cors/

我假设您打算写 ashx,而不是 ascxProcessRequest (HttpContext context) 方法的存在表明它是通用处理程序而不是用户控件。

我制作了一个非常简单的页面来测试:

<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="Scripts/jquery-1.4.1.js"></script>
</head>
<body>
    <div id="testCorsDiv">
    </div>
    <script type="text/javascript">
        $.ajax({
            type: "GET",
            url: "/Handler/testCors.ashx",
            dataType: "text",
            success: function (theData) { $("#testCorsDiv").text(theData); },
            error: function (theData) { alert('error'); }
        });
    </script>
    <% if(string.IsNullOrEmpty(Request.QueryString["sandboxed"])) { %>
    <iframe src="http://127.0.0.1:49253/SandboxTest.aspx?sandboxed=true" sandbox="allow-scripts" width="600">
    </iframe>
    <% } %>
</body>
</html>

我在 http://localhost:49253/SandboxTest.aspx 加载页面。该页面然后向 http://localhost:49253/Handler/testCors.ashx 发出 ajax 请求并将其输出放入 testCorsDiv div。这会直接向处理程序生成 GET(因为它来自同一来源)并插入输出。

页面中还有一个沙盒 iframe,它使用 url http://127.0.0.1:49253/SandboxTest.aspx 加载同一页面。 ?sandboxed=true 用于防止 iframe 递归加载内部 iframe。然后,加载到 iframe 中的页面将尝试向 http://127.0.0.1:49253/Handler/testCors.ashx 发出 ajax 请求,并在它自己的 testCorsDiv div.

副本中显示输出

只要沙盒 iframe 有 allow-scripts,这就很有魅力了。 iframe 生成如下所示的 OPTIONS 请求(来自 Fiddler,使用 Chrome 测试):

OPTIONS http://127.0.0.1:49253/Handler/testCors.ashx HTTP/1.1
Host: 127.0.0.1:49253
Connection: keep-alive
Cache-Control: max-age=0
Access-Control-Request-Method: GET
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90     Safari/537.36
Access-Control-Request-Headers: accept, x-requested-with
Accept: */*
Referer: http://127.0.0.1:49253/SandboxTest.aspx?sandboxed=true
Accept-Encoding: gzip, deflate, sdch
Accept-Language: fi-FI,fi;q=0.8,en-US;q=0.6,en;q=0.4

我的 testCors.ashx 处理程序然后吐出一些 headers 说这看起来 ay-ok 然后浏览器跟进 GET 并且它正常工作。

testCors.ashx 这样做:

public void ProcessRequest(HttpContext context)
{
    context.Response.ContentType = "text/plain";
    context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
    context.Response.AppendHeader("Access-Control-Allow-Headers", "content-type, x-requested-with, accept");
    context.Response.AppendHeader("Access-Control-Allow-Methods", "POST, OPTIONS, GET");
    context.Response.Write("Hello World");
}

所以我的测试表明应该可以做你想做的事。尽管这可能是一个问题,但如果您的处理程序只能由 authenticated/authorized 用户访问。如您所见,OPTIONS 请求尚未向处理程序发送 cookie。但另一方面,您的问题表明对您的选项请求的响应是 Status Code:200。我想如果缺少必需的身份验证 cookie,那将是一些 4**

总结一下,我真的不知道你的情况出了什么问题,但也许(?)我的简单示例页面可以给你一些线索,帮助你自己找到问题。

您遇到的错误:

XMLHttpRequest cannot load https://127.0.0.1:112/handlers/gettoken.ashx. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

是因为您的应用程序已免受点击劫持攻击。在您的情况下,您的应用程序 web.config 中的 X-Fame-Options 可能设置为 Deny,将其设置为 'SAMEORIGIN' 将有助于解决您的问题,前提是您的应用程序具有与你的 iframe.

这是这样做的:

<system.webServer>
      <httpProtocol>
         <customHeaders>
            <add name="X-Frame-Options" value="SAMEORIGIN" />
         </customHeaders>
      </httpProtocol>
</system.webServer>

如果你能找到解决这个问题的方法(我的意思是让你的应用程序在设置了拒绝选项的 iframe 中工作),那么它会破坏拥有这样一个功能的唯一目的(防止点击劫持的安全性)。

希望对您有所帮助。