13

我正在通过 POST 请求跨域发送数据,但响应不起作用,特别是 jQuery 的成功处理程序永远不会被调用。

使用的东西:Django、Apache、jQuery。

因此,我设置了一个与此类似的请求:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "POST",
    cache: false,
    dataType: "json",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});

如您所知,CORS允许我OPTIONS适当地回复查询,说“是的,您可以向我发送邮件”。我正在做的。Firebug 确认我得到了我的200状态码并且返回类型实际上是application/json. 但是,Firebug 也确认上面的成功处理程序没有被调用。

作为参考,我的回应OPTIONS是:

elif request.method == "OPTIONS":
    response = HttpResponse("")
    response['Access-Control-Allow-Origin'] = "*"
    response['Access-Control-Allow-Methods'] = "POST, GET, OPTIONS"
    response['Access-Control-Allow-Headers'] = "X-Requested-With"
    return response

相反,如果我设置了一个complete: function()...处理程序,它就可以工作。

所以,问题是:发生了什么(或没有发生),为什么?我得到的数据很好,我只想能够返回响应。


更新这解决了我在某些浏览器上的问题,但由于我对此行为没有完整的明确解释,所以我将其保持打开状态

好的,所以我阅读了手册以及我对它的理解,所应用的算法大致是这样的:

  1. 用户代理可以实现预检调用。这是OPTIONS请求。这个想法是他们提出这个请求,这给他们一个关于所请求资源的答案,然后他们应该缓存这些资源。我没有传回 max-age字段,所以我怀疑在返回成功并且允许 X 请求时,用户代理的缓存中没有任何内容允许我这样做,所以默认规则(隔离请求) 被应用。
  2. 当您发出实际请求时,我相信用户代理应该检查飞行前缓存的权限。如果没有我的 max-age 字段,我相信它找不到这些权限。但是,使用相同的标题进行响应POST似乎允许 Firefox 和 Google Chrome 查看响应。歌剧不能。IE 目前还没有经过测试。

我目前不明白,并且从手册中(至少对我而言)不清楚 CORS 请求是否也应该在请求中使用这些标头以及OPTIONS. 我将试验Max-Age标题,看看允许或不允许什么。但是,我对这个问题仍然缺乏一定的权威理解,所以如果这里有人知道,我会全神贯注。

4

4 回答 4

17

好的,所以我相信正确的做事方式是这样的:

if request.method == "POST":
    response = HttpResponse(simplejson.dumps(data),mimetype='application/json')
    response['Access-Control-Allow-Origin'] = "*"
    return response
elif request.method == "OPTIONS":
    response = HttpResponse("")
    response['Access-Control-Allow-Origin'] = "*"
    response['Access-Control-Allow-Methods'] = "POST, OPTIONS"
    response['Access-Control-Allow-Headers'] = "X-Requested-With"
    response['Access-Control-Max-Age'] = "1800"
else:
    return HttpResponseBadRequest()

这是基于我从 Mozilla 挖掘的关于预检请求的文档。

所以,我相信会发生的是:

  1. 如果预检缓存中没有任何内容,OPTIONS则发送X-Requested-With设置为XMLHttpRequest我相信这是允许 Javascript 访问任何内容以及Origin标头所必需的。
  2. 服务器可以检查该信息。这就是 CORS 的安全性。就我而言,我的回应是“任何来源都可以”和“你可以发送X-Requested-With东西”。我说的OPTIONSPOST允许的,并且这个响应应该被缓存 30 分钟。
  3. 客户端然后继续进行 POST,这在以前是有效的。
  4. 我最初修改了响应以包含Allow-MethodsAllow-Headers但根据上述链接文档中的交换,这不是必需的。这是有道理的,访问检查已经完成。
  5. 我相信会发生这里描述的资源共享检查。基本上,一旦提出了所述请求,浏览器就会再次检查该Allow-Origin字段的有效性,这在请求上,例如POST. 如果通过,客户端可以访问数据,如果没有,则请求已经完成,但浏览器拒绝实际的客户端应用程序 (Javascript) 访问该数据。

我相信这是对正在发生的事情的正确总结,无论如何它似乎有效。如果我说的不对,请大声疾呼。

于 2011-03-10T13:09:42.570 回答
1

对于任何可能遇到此帖子的未来搜索者,以下资源是 W3C 2008 工作草案,其中深入讨论了 CORS。

http://www.w3.org/TR/2008/WD-access-control-20080912/

截至本文发布之时,应该注意的是 Chromium,并且可能所有的 WebKit 都有一个错误,该错误会阻止Access-Control-Max-Age标头的值被兑现。可以在Chromium 问题 131368的讨论页面上找到有关此内容的详细信息。总之——截至目前,基于 WebKit 的浏览器将覆盖服务器返回的任何值600(10 分钟)。

于 2012-12-14T05:54:50.000 回答
0

要求:

 $.ajax({
            url: "http://localhost:8079/students/add/",
            type: "POST",
            crossDomain: true,
            data: JSON.stringify(somejson),
            dataType: "json",
            success: function (response) {
                var resp = JSON.parse(response)
                alert(resp.status);
            },
            error: function (xhr, status) {
                alert("error");
            }
        });

回复:

response = HttpResponse(json.dumps('{"status" : "success"}'))
response.__setitem__("Content-type", "application/json")
response.__setitem__("Access-Control-Allow-Origin", "*")

return response
于 2013-12-06T12:29:35.550 回答
-2

出于安全原因,我认为这是不可能的。浏览器允许的唯一跨域 ajax 调用可以使用 JSONP 完成,并且这些都是 GET 请求。

这将起作用:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "GET",
    cache: false,
    dataType: "JSONP",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});

这不会:

$.ajax({
    url: "http://somesite.com/someplace",
    type: "POST",
    cache: false,
    dataType: "JSONP",
    data: { ... },
    success: function( msg ) {
        alert(msg);
    },
});
于 2011-03-10T08:03:19.443 回答