通过 AJAX 进行跨域资源共享 (CORS)
Posted
技术标签:
【中文标题】通过 AJAX 进行跨域资源共享 (CORS)【英文标题】:Cross Origin Resource Sharing (CORS) via AJAX 【发布时间】:2017-10-06 17:07:44 【问题描述】:我知道有很多关于这个主题的问题,我已经尝试解决这个问题一段时间了。请纵容我在这个特定的情况下。
我的目标:
我正在尝试从以下 URL 获取 JSON 数据:
https://www.icims.com/bellworks
我正在使用以下 AJAX 请求:
$.ajax(
url: "https://www.icims.com/bellworks",
success: function(res)
console.log(res);
);
我的问题:
我收到以下错误:
跨域请求被阻止:同源策略不允许读取 https://www.icims.com/bellworks 的远程资源。 (原因:CORS 预检通道未成功)。
尽管直接访问 URL 会在标头中提供以下内容:
Access-Control-Allow-Origin: *
我已经下载了支持 CORS 的 Firefox 和 Chrome 扩展程序,这很有效!我能够得到数据。
我的问题:
这些 CORS 插件在做什么,我没有?
显然,这是我需要添加到 源端的客户端的东西,对吗?也就是说,我需要对我的 AJAX 请求进行更改。我确实不需要对响应服务器进行任何更改。
我需要在我的请求中添加什么来纠正这个问题?
【问题讨论】:
见这里:developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS 你试过了吗? ***.com/a/42554319/2506219 标头放在 GET 请求上,但没有 OPTIONS 预检请求。 您对该网址的响应看起来更像jsonp
- 它有一个围绕 json 的方法调用。 bellway(...json...)
即,即使您确实设法发出 CORS 请求,您也无法解析 json。这将是无效的。
【参考方案1】:
“原因:CORS 预检通道未成功”
从您的错误消息中可以看出,ajax 调用会生成一个被 cors 阻止的“选项”请求。 (访问控制允许方法)
检查一下,也许有帮助:https://enable-cors.org/server_nginx.html
【讨论】:
【参考方案2】:服务器响应还应包含此标头:“Access-Control-Allow-Methods”。它的值可以是“POST, GET, OPTIONS”以允许预检请求。见文档。 https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods
【讨论】:
【参考方案3】:我收到以下错误:
跨域请求被阻止:同源策略不允许读取 https://www.icims.com/bellworks 的远程资源。 (原因:CORS 预检通道未成功)。
尽管直接访问 URL 会得到以下结果 在标题中:
Access-Control-Allow-Origin: *
你在哪里看到的?我在来自https://www.icims.com/bellworks
的响应中根本看不到任何Access-Control-Allow-Origin
响应标头——在浏览器开发工具中也没有,例如curl
:
$ curl -i -H "Origin: http://example.com" https://www.icims.com/bellworks
HTTP/1.1 200 OK
Age: 141
Cache-Control: public, max-age=1800
Content-Type: application/javascript; charset=utf-8
Date: Tue, 09 May 2017 10:17:38 GMT
Etag: "1494323930-1"
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Tue, 09 May 2017 09:58:50 GMT
Server: nginx
Vary: Cookie,Accept-Encoding
Via: 1.1 varnish
X-AH-Environment: prod
X-Cache: HIT
X-Cache-Hits: 2
X-Content-Type-Options: nosniff
X-Drupal-Cache: HIT
X-Request-ID: v-66496654-34a0-11e7-ba07-22000a2c8dd2
X-Varnish: 2264707046 2264675783
Content-Length: 6443
Connection: keep-alive
在这样的简单情况下,如果 1) 您不控制要从前端 JS 代码中获取数据的服务器,并且 2) 该服务器未在其响应中发送 Access-Control-Allow-Origin
,您可以更改您的前端代码改为通过开放的 CORS 代理发出请求:
$.ajax(
url: "https://cors-anywhere.herokuapp.com/https://www.icims.com/bellworks",
…
);
这将导致向https://cors-anywhere.herokuapp.com
发出请求,然后将其发送到https://www.icims.com/bellworks
的代理。当该代理收到响应时,它会接受它并向其添加Access-Control-Allow-Origin
响应标头,然后将其作为响应传递回您的请求前端代码。
带有Access-Control-Allow-Origin
响应标头的响应是浏览器看到的,因此浏览器引擎现在向您显示的错误消息消失了,浏览器允许您的前端 JavaScript 代码访问响应。
或者使用https://github.com/Rob--W/cors-anywhere/的代码或者类似的代码来设置你自己的代理。
这些 CORS 插件做了哪些我没有做的事情?
它们的不同之处在于,它们只是没有被浏览器阻止。插件可以做任何他们想做的事——包括绕过浏览器对前端 JavaScript 代码施加的跨域限制,浏览器执行代码的时候是在其中。
浏览器 devtools 也不受跨域限制的影响——如果您使用 devtools 检查收到 Cross-Origin Request Blocked
消息的请求,您会注意到您实际上可以在 devtools 中看到响应。但这并不意味着浏览器一定会将响应暴露给您的前端 JavaScript 代码。如果响应包含 Access-Control-Allow-Origin
标头,浏览器只会让您的前端 JavaScript 代码访问它。
显然,这是我需要添加到 源端的客户端的东西,对吗?
没有。您在客户端执行的任何操作都不会改变这样一个事实:如果您的前端 JS 代码发出跨域请求并且响应不包含 Access-Control-Allow-Origin
标头,您的浏览器将阻止您的代码访问响应。期间。
也就是说,我需要对我的 AJAX 请求进行更改。
不,因为上面给出的原因。
我确实不需要对响应服务器进行任何更改。
您确实需要更改响应服务器以发送Access-Control-Allow-Origin
标头。或者如上所述,您需要通过代理发送请求,该代理会将Access-Control-Allow-Origin
标头添加到浏览器看到的响应中。
我需要在我的请求中添加什么来纠正这个问题?
如果您无法控制发出请求的服务器,那么您唯一的选择就是更改代码,改为通过添加了Access-Control-Allow-Origin
的代理发出请求。
【讨论】:
以上是关于通过 AJAX 进行跨域资源共享 (CORS)的主要内容,如果未能解决你的问题,请参考以下文章
需要使用 jQuery Ajax 使用 Web API - 跨域资源共享 (CORS) 问题