对预检请求的响应未通过访问控制检查错误
Posted
技术标签:
【中文标题】对预检请求的响应未通过访问控制检查错误【英文标题】:Response to preflight request doesn't pass access control check error 【发布时间】:2018-01-19 09:53:51 【问题描述】:我正在努力解决的确切错误是“对预检请求的响应未通过访问控制检查:所请求的资源上不存在'Access-Control-Allow-Origin'标头。因此没有来源'null'允许访问。”。
我正在尝试使用 javascript 从 https://api.kraken.com/0/public/OHLC?pair=ETHEUR 获取 JSON 数据。为此,我创建了一个 XMLHttpRequest 对象,并将 GET 指定为请求类型。这应该是一个简单的请求,但是错误表明发送了预检请求。这种行为的原因是什么?话虽这么说,为了解决这个错误,我尝试设置一个请求标头,在其中我指定“*”作为 Access-Control-Allow-Origin 的值,但我仍然收到错误消息。我查看了对与我类似的问题的回答,但无法弄清楚如何解决我正在处理的问题。这可能是由于对 JavaScript 还是很陌生。不管怎样,下面是我写的代码:
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR'
var request = new XMLHttpRequest();
request.open('GET',requestURL,true);
request.responseType = 'json';
request.onload = function()
var data = request.response;
console.log(data);
request.setRequestHeader('Access-Control-Allow-Origin','*');
request.send();
【问题讨论】:
request.setRequestHeader('Access-Control-Allow-Origin','*')
的目的是什么?
这个错误告诉我提供一个 Access-Control-Allow-Origin,因此我添加了那行代码。显然,它并没有解决问题。
错误通知您请求的资源没有Access-Control-Allow-Origin
标头“请求的资源上不存在'Access-Control-Allow-Origin'标头。” 你想从file:
协议中创建一个XMLHttpRequest()
吗?
是的,我该怎么做呢? (我假设使用 file: 协议,您的意思是发送请求的域是我编写上述代码的文件的路径。)
在 Chrome、Chromium 浏览器中,您可以启动带有 --allow-file-access-from-files
标志的新浏览器实例,请参阅 Read local XML with JS
【参考方案1】:
在这种情况下,您尝试向其发出跨域请求的服务器不发送 Access-Control-Allow-Origin
响应标头,这是您唯一的选择,如果您想从前端 JavaScript 向该服务器发出请求在浏览器中运行的代码是使用 CORS 代理。否则,您的浏览器将不允许您的前端 JavaScript 代码访问响应。
因此,如果您将代码更改为具有以下内容,则可以使您的请求成功:
var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';
var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);
通过https://cors-anywhere.herokuapp.com 发送请求,https://cors-anywhere.herokuapp.com 将请求转发到https://api.kraken.com/0/public/OHLC?pair=ETHEUR
,然后接收响应。 https://cors-anywhere.herokuapp.com
后端将 Access-Control-Allow-Origin
标头添加到响应中,并将其传递回您的请求前端代码。
然后浏览器将允许您的前端代码访问响应,因为带有Access-Control-Allow-Origin
响应标头的响应是浏览器看到的。
您还可以使用 https://github.com/Rob--W/cors-anywhere/ 轻松设置自己的 CORS 代理
另请注意,request.setRequestHeader('Access-Control-Allow-Origin','*')
需要从您发出请求的前端代码中删除(如上面的 cmets 所述)。
这是因为Access-Control-Allow-Origin
严格来说是一个response 标头,供服务器发送响应;在请求中从客户端发送它除了触发您的浏览器执行不必要的 CORS preflight OPTIONS request 之外没有任何效果,这将失败。
详细了解当您使用 XHR 或 JavaScript 库中的 Fetch API 或 AJAX 方法从前端 JavaScript 代码发送跨域请求时浏览器会做什么,以及有关必须接收哪些响应标头才能让浏览器允许前端代码的详细信息访问回复——请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS。
var proxyURL = 'https://cors-anywhere.herokuapp.com';
var requestURL = 'https://api.kraken.com/0/public/OHLC?pair=ETHEUR';
var request = new XMLHttpRequest();
request.open('GET', proxyURL + '/' + requestURL, true);
request.responseType = 'json';
request.onload = function()
var data = request.response;
document.querySelector('pre').textContent = JSON.stringify(data, null, 2);
request.send();
<pre></pre>
【讨论】:
感谢您的详细解释,以及我可以在哪里了解有关跨源请求如何工作的更多信息的参考。也就是说,我尝试按照您的建议使用 CORS 代理来实现我的请求。但是这样做我无法检索驻留在 requestURL 上的 JSON 数据,而是请求获取 proxyURL 上的内容。 请使用request.open('GET', 'https://cors-anywhere.herokuapp.com/https://api.kraken.com/0/public/OHLC?pair=ETHEUR', true)
重试,它将准确返回您需要的内容。请参阅我添加到答案中的代码 sn-p。 (在最初答案的代码中,我在proxyURL
值中留下了一个尾随/
,这会导致请求无法按预期工作。)
如果https://cors-anywhere.herokuapp.com
出现故障或不可用怎么办。你从哪里得到这些代理?
@shorif2000 见***.com/questions/47076743/…。如果您有 Heroku 帐户,您可以在 2-3 分钟内启动自己的 CORS 代理以上是关于对预检请求的响应未通过访问控制检查错误的主要内容,如果未能解决你的问题,请参考以下文章