没有为OPTIONS Ajax请求设置标头

时间:2015-04-14 17:36:12

标签: asp.net ajax iis-7 get access-control

我有ascxGetToken.ashx

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

当我对此页面进行AJAX时,它会返回以下标题:

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.

并返回标题:

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

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

5 个答案:

答案 0 :(得分:6)

我认为您打算写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上加载页面。然后,该页面向ajax发出http://localhost:49253/Handler/testCors.ashx请求,并将其输出放入testCorsDiv div。这会为处理程序生成一个直的GET(因为它来自同一个来源)并且输出会被插入。

在该页面中还有一个沙盒iframe,它使用网址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处理程序然后吐出一些标题,说明这看起来很好,然后浏览器跟进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");
}

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

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

答案 1 :(得分:1)

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

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

  • 选择所需的应用程序池
  • 点击处理程序映射
  • 选择* .ashx并双击相应的处理程序,点击请求限制,看看你是否有选项动词,如果没有,请添加。

此处提及 - 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,但它也适用于您的情况!您可能需要将允许来源的*更改为请求的来源,因为*存在安全问题,它允许所有域进行CORS呼叫。

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

在没有allow-same-origin选项的沙盒iframe中,制作AJAX请求似乎是绝对不可能的。

有关详细说明,请参阅此答案:IFRAME sandbox attribute is blocking AJAX calls

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

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

答案 4 :(得分:0)

你得到的错误:

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.

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

这就是它的完成方式:

iframe

如果你能找到解决方法(我的意思是让你的应用程序在设置了拒绝选项的情况下在iframe中工作),那么它将失去具有这种功能的唯一目的(防止点击劫持的安全性)。

希望这有帮助。

相关问题