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

2022-01-15 00:00:00 cors xmlhttprequest jquery javascript ajax

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

I attempt to send a GET request in a jQuery AJAX request.

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

但是,无论我尝试过什么,我都得到 XMLHttpRequest 无法加载 <page>.请求的资源上不存在Access-Control-Allow-Origin"标头.因此不允许访问 Origin 'http://localhost:7776'.

However, whatever I've tried, I got 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 的插件 - 但没有任何帮助.

I tried everything, from adding header : {} definitions to the AJAX request to setting dataType to JSONP, or even text/plain, using simple AJAX instead of jQuery, even downloading a plugin that enables CORS - but nothing could help.

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

And the same happens if I attempt to reach any other sites.

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

Any ideas for a proper and simple solution? Is there any at all?

推荐答案

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

This is by design. You can't make an arbitrary HTTP request to another server using XMLHttpRequest unless that server allows it by putting out an Access-Control-Allow-Origin header for the requesting host.

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

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

You could retrieve it in a script tag (there isn't the same restriction on scripts and images and stylesheets), but unless the content returned is a script, it won't do you much good.

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

Here's a tutorial on CORS:

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

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

This is all done to protect the end user. Assuming that an image is actually an image, a stylesheet is just a stylesheet and a script is just a script, requesting those resources from another server can't really do any harm.

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

But in general, cross-origin requests can do really bad things. Say that you, Zoltan, are using coolsharks.com. Say also that you are logged into mybank.com and there is a cookie for mybank.com in your browser. Now, suppose that coolsharks.com sends an AJAX request to mybank.com, asking to transfer all your money into another account. Because you have a mybank.com cookie stored, they successfully complete the request. And all of this happens without your knowledge, because no page reload occurred. This is the danger of allowing general cross-site AJAX requests.

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

If you want to perform cross-site requests, you have two options:

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

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

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

In (1), you must have the cooperation of the server you are making requests to, and in (2), you must have control over the end user's browser. If you can't fulfill (1) or (2), you're pretty much out of luck.

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

However, there is a third option (pointed out by charlietfl). You can make the request from a server that you do control and then pass the result back to your page. E.g.

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

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

And then on your server, at its most simple:

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

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

Of course, this method may run into other issues:

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

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

I'm sure there are others. But if none of those issues prevent it, this third method could work quite well.

相关文章