AJAX 请求获取“请求的资源上不存在‘Access-Control-Allow-Origin’标头”错误

Posted

技术标签:

【中文标题】AJAX 请求获取“请求的资源上不存在‘Access-Control-Allow-Origin’标头”错误【英文标题】:AJAX request gets "No 'Access-Control-Allow-Origin' header is present on the requested resource" error 【发布时间】:2016-05-20 04:36:15 【问题描述】:

我尝试在 jQuery AJAX 请求中发送 GET 请求。

$.ajax(
    type: 'GET',
    url: /* <the link as string> */,
    dataType: 'text/html',
    success: function()  alert("Success"); ,
    error: function()  alert("Error"); ,
);

但是,无论我尝试过什么,我都得到了XMLHttpRequest cannot load &lt;page&gt;. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:7776' is therefore not allowed access.

我尝试了一切,从将 header : 定义添加到 AJAX 请求到将 dataType 设置为 JSONP,甚至 text/plain,使用简单的 AJAX 而不是 jQuery,甚至下载了启用 CORS 的插件 - 但没有可以帮忙。

如果我尝试访问任何其他网站,也会发生同样的情况。

对于适当且简单的解决方案有任何想法吗?有吗?

【问题讨论】:

您不能向另一个域发出 ajax 请求,因为 CORS(跨域资源共享),除非另一个域(在本例中为 ***)允许。 你不能单独在浏览器上绕过同源策略,因为它会完全违背它的目的。 @Juhana 这个答案也是来自 Stack Overflow! 不知道你想说什么,但没关系。 @Juhana 您的评论暗示浏览器插件是解决此问题的荒谬且荒谬的方法。我强调这样做的想法也来自这个网站,我认为这表明即使在这里,也可以给出糟糕的答案而无需投票。这很可悲,但我当然不会评判网站质量。 【参考方案1】:

这是设计使然。您不能使用 XMLHttpRequest 向另一台服务器发出任意 HTTP 请求,除非该服务器通过为请求主机提供 Access-Control-Allow-Origin 标头来允许它。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

您可以在脚本标签中检索它(对脚本、图像和样式表没有相同的限制),但除非返回的内容是脚本,否则对您没有多大用处。

这里有一个关于 CORS 的教程:

http://www.bennadel.com/blog/2327-cross-origin-resource-sharing-cors-ajax-requests-between-jquery-and-node-js.htm

这一切都是为了保护最终用户。假设图像实际上是图像,样式表只是样式表,脚本只是脚本,从另一台服务器请求这些资源不会真正造成任何伤害。

但总的来说,跨域请求可能会做一些非常糟糕的事情。假设您,Zoltan,正在使用coolsharks.com。还要说您已登录 mybank.com,并且您的浏览器中有一个 mybank.com 的 cookie。现在,假设coolsharks.com 向mybank.com 发送了一个AJAX 请求,要求将您的所有资金转入另一个帐户。因为您存储了 mybank.com cookie,所以他们成功完成了请求。所有这一切都是在您不知情的情况下发生的,因为没有发生页面重新加载。这是允许一般跨站点 AJAX 请求的危险。

如果要执行跨站请求,有两种选择:

    将您发出请求的服务器获取到 一种。通过发布包含您(或 *)的 Access-Control-Allow-Origin 标头来承认您 湾。为您提供 JSONP API。

    编写自己的浏览器,不遵循标准,没有限制。

在 (1) 中,您必须与您正在向其发出请求的服务器合作,并且在 (2) 中,您必须能够控制最终用户的浏览器。如果你不能满足 (1) 或 (2),那你就很不走运了。

但是,还有第三种选择(charlietfl 指出)。您可以从您控制的服务器发出请求,然后将结果传回您的页面。例如

<script>
$.ajax(
    type: 'GET',
    url: '/proxyAjax.php?url=http%3A%2F%2F***.com%2F10m',
    dataType: 'text/html',
    success: function()  alert("Success"); ,
    error: function()  alert("Error"); 
);
</script>

然后在您的服务器上,最简单:

<?php
// proxyAjax.php
// ... validation of params
// and checking of url against whitelist would happen here ...
// assume that $url now contains "http://***.com/10m"
echo file_get_contents($url);

当然,这种方法可能会遇到其他问题:

您作为代理的网站是否需要正确的引荐来源网址或特定 IP 地址? 是否需要将 cookie 传递到目标服务器? 您的白名单是否足以保护您免于提出任意请求? 当您的服务器接收到它们时,您会将哪些标头(例如修改时间等)传递回浏览器,您会忽略或更改哪些标头? 您的服务器是否会被牵连提出非法请求(因为您是代理)?

我确定还有其他人。但是,如果这些问题都没有阻止它,那么第三种方法可以很好地工作。

【讨论】:

缺少#3,即在您控制的域上使用代理来发出请求并返回想要的资源 还有第三方代理,比如 Yahoo YQL 感谢您的解释!这是否意味着(如果我不想使用代理,那么)我在任何情况下获得 JSONP API 时唯一的方法? @Zoltan。是的,在不使用代理的情况下,在尝试从流行站点请求页面时,获取 JSONP API 将是您的最佳选择。 (他们不太可能将您的来源或 * 放在他们的标题中。)但请记住,JSONP API 通常不是为请求站点的任意可导航页面而创建的(例如您问题中的“/10m”链接.)。它通常用于接收 JSON 而不是 HTML 的地方。 因此,有些网站在任何情况下我都无法GET,对吗?当然没有代理。【参考方案2】:

您可以询问该域的开发人员是否会为您设置适当的标头,此限制仅适用于 javascript,基本上您可以使用 php 或其他方式从您的服务器请求资源,而 javascript 会从您的域请求数据那么

【讨论】:

如果 - 在这种特殊情况下 - 我通过 SE API 对自己进行身份验证,这是否有帮助? 我不知道这个 api,但是如果提供者提供了一个用于 javascript 使用的 api,他们将提供一个适用于 js 请求的 api【参考方案3】:

老问题,但我在任何地方都没有看到这个对我有用的解决方案。所以希望这对某人有帮助。

首先,请记住,尝试修改 request 的标头以绕过跨域资源请求是没有意义的。如果仅此而已,那么恶意用户很容易绕过此安全措施。

只有在合作伙伴网站的服务器通过其 response 标头允许的情况下,此上下文中的跨域请求才可能发生。

通过在响应中设置以下标头,我让它在没有任何 CORS 中间件的情况下在 Django 中工作:

    response["Access-Control-Allow-Origin"] = "requesting_site.com"
    response["Access-Control-Allow-Methods"] = "GET"
    response["Access-Control-Allow-Headers"] = "requesting_site.com"

这里的大多数答案似乎都提到了第一个,但没有提到第二个。我刚刚确认它们都是必需的。您需要根据框架或请求方法(GET、POST、OPTION)的需要进行修改。

附言您可以尝试 "*" 而不是 "requesting_site.com" 进行初始开发以使其正常工作,但允许每个站点访问将是一个安全漏洞。工作后,您可以将其限制为您的请求站点,以确保您没有任何格式错误。

【讨论】:

以上是关于AJAX 请求获取“请求的资源上不存在‘Access-Control-Allow-Origin’标头”错误的主要内容,如果未能解决你的问题,请参考以下文章

Ajax 和 Places API 获取请求

Django通过ajax获取请求发出两个请求

$.ajax 获取请求

为啥我无法从 ajax 发布请求中获取操作

vue中的ajax请求

Symfony 5 / 请求响应:使用 Ajax 获取数据