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 <page>. 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’标头”错误的主要内容,如果未能解决你的问题,请参考以下文章