CORS 已启用,但仍出现 CORS 错误
Posted
技术标签:
【中文标题】CORS 已启用,但仍出现 CORS 错误【英文标题】:CORS enabled but still getting CORS error 【发布时间】:2017-04-29 16:13:52 【问题描述】:我正在尝试从 API 获取 JSON 对象,API 的开发人员说他们刚刚启用了 CORS,但我仍然收到以下错误。
XMLHttpRequest 无法加载 http://example.com/data/action/getGame/9788578457657。请求的资源上不存在“Access-Control-Allow-Origin”标头。 Origin 'http://dev.our-domain.local' 因此不允许访问。
我正在使用 AngularJS 在服务中获取 JSON
app.service("gameService", function ($http, $q)
function getGame(GameId)
var deferred = $q.defer()
var url = 'http://example.com/data/action/getGame/' + gameId;
// var url = 'https://jsonplaceholder.typicode.com/albums/' + gameId; // THIS WORKS
$http(
method: 'GET',
cache: true,
url: url,
headers:
'Content-Type': 'application/json;charset=UTF-8'
).
then(function(response)
//your code when success
deferred.resolve(response);
console.log('gameService HTTP CORS SUCCESS!');
, function(response)
//your code when fails
console.log('gameService HTTP CORS ERROR!');
// deferred.resolve('');
deferred.reject(response);
);
return deferred.promise;
this.getGame = getGame;
)
当我使用启用了 CORS 的 jsonplaceholder 对其进行测试时,我的 AngularJS 服务可以正常工作。
我错过了什么吗?
API 开发人员说两个 CORS 标头已添加到 data.service 响应中,但我没有看到它们。这是我在 curl
向下 JSON 对象时看到的标题。
$ curl -X HEAD -i http://example.com/data/action/getGame/9788578457657
HTTP/1.1 200 OK
Date: Wed, 14 Dec 2016 10:39:17 GMT
Server: WildFly/8
Expires: Wed, 14 Dec 2016 10:39:17 GMT
X-Powered-By: Undertow/1
X-dmg-elapsed-time: 20ms
X-dmg-host-address: 1??.??.???.??
Vary: Accept-Encoding,Origin
X-dmg-generated-time: Wed, 14 Dec 2016 10:39:17 GMT
Content-Type: application/json;charset=UTF-8
Content-Language: en-
X-dmg-node-name: defg_node_1
X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
X-Varnish-Bereq-Retries: 0
Last-Modified: Wed, 14 Dec 2016 10:39:17 GMT
Cache-Control: public, max-age=300
X-Varnish: 6876870
Age: 0
Via: 1.1 varnish-v4
X-Varnish-Cache: MISS
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool: http_pages
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-Varnish-Hash: /data/action/getGame/9788578457657
X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
X-DMG-Version: 6.20.51.2358
Accept-Ranges: none
Connection: keep-alive
这是启用 CORS 后我应该看到的还是有更多?
在启用 Cors 的情况下,我是否需要向我的 AngularJS 服务添加更多内容,以添加更多内容:
headers:
'Content-Type': 'application/json;charset=UTF-8'
更新
传递来源:在我的 curl 请求的标头中,如 @t.niese 建议的那样
$ curl -H "Origin: http://our-production-domain.com/" --verbose \
> http://example.com/data/action/getGame/9788578457657
* Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://our-production-domain.com/
>
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:05:24 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:05:24 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 27ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:05:24 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:05:24 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 6876870
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges: none
< Transfer-Encoding: chunked
< Connection: keep-alive
<
"errorMessage" : null,
"expiry" : "2016-12-14T11:05:24.379+0000",
"data" :
// json object data here
* Connection #0 to host http://example.com/ left intact
和..
$ curl -H "Origin: http://qa.our-qa-domain.com/" --verbose \
> http://example.com/data/action/getGame/9788578457657
* Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://qa.our-qa-domain.com/
>
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:06:11 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:06:11 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 18ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:06:11 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:06:11 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 1343699
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges: none
< Content-Length: 2988
< Connection: keep-alive
<
"errorMessage" : null,
"expiry" : "2016-12-14T11:06:11.927+0000",
"data" :
// json data object here
* Connection #0 to host http://example.com/ left intact
和..
$ curl -H "Origin: http://dev.my-dev.local/" --verbose \
> http://example.com/data/action/getGame/9788578457657
* Trying 1?.???.??.???...
* Connected to http://example.com/ (1?.???.??.???) port 80 (#0)
> GET /data/action/getGame/9788578457657 HTTP/1.1
> Host: http://example.com/
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://dev.my-dev.local/
>
< HTTP/1.1 200 OK
< Date: Wed, 14 Dec 2016 11:07:10 GMT
< Server: WildFly/8
< Expires: Wed, 14 Dec 2016 11:07:10 GMT
< X-Powered-By: Undertow/1
< X-dmg-elapsed-time: 28ms
< X-dmg-host-address: 1??.??.???.??
< Vary: Accept-Encoding,Origin
< X-dmg-generated-time: Wed, 14 Dec 2016 11:07:10 GMT
< Content-Type: application/json;charset=UTF-8
< Content-Language: en-
< X-dmg-node-name: defg_node_1
< X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
< X-Varnish-Bereq-Retries: 0
< Last-Modified: Wed, 14 Dec 2016 11:07:10 GMT
< Cache-Control: public, max-age=300
< X-Varnish: 6619151
< Age: 0
< Via: 1.1 varnish-v4
< X-Varnish-Cache: MISS
< X-Varnish-Trimen: www.trimen.com
< X-Varnish-Served-By-Host: snarf.foo.uk
< X-Varnish-Served-By-IP: 100.100.10.80
< X-Varnish-Pool: http_pages
< X-Varnish-Req-Backend-Hint: dead
< X-Varnish-Req-Restarts: 0
< X-Varnish-Hash: /data/action/getGame/9788578457657
< X-Varnish-Backend-Ourself: varnish_server_snarf_foo_uk
< X-DMG-Version: 6.20.51.2358
< Accept-Ranges: none
< Content-Length: 2988
< Connection: keep-alive
<
"errorMessage" : null,
"expiry" : "2016-12-14T11:07:10.764+0000",
"data" :
// JSON object data here
* Connection #0 to host http://example.com/ left intact
第二次更新
我在 Chrome 中禁用了同源策略,这些是来自 Chrome 网络面板的 JSON 请求的标头。
GET data/action/getGame/9788578457657 HTTP/1.1
Host: example.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://dev.my-dev.local/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Referer: http://dev.my-dev.local//game/id-9788578457657
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
HTTP/1.1 200 OK
Date: Wed, 14 Dec 2016 15:38:38 GMT
Server: WildFly/8
Expires: Wed, 14 Dec 2016 15:38:38 GMT
X-Powered-By: Undertow/1
X-dmg-elapsed-time: 25ms
X-dmg-host-address: 172.16.0.70
Vary: Accept-Encoding,Origin
X-dmg-generated-time: Wed, 14 Dec 2016 15:38:38 GMT
Content-Type: application/json;charset=UTF-8
Content-Language: en-
X-dmg-node-name: defg_node_1
Content-Encoding: gzip
Content-Length: 1109
X-Varnish-Bereq-Backend: real_backend_foo_bar_uk
X-Varnish-Bereq-Retries: 0
Last-Modified: Wed, 14 Dec 2016 15:38:38 GMT
Cache-Control: public, max-age=300
X-Varnish: 6619151
Age: 0
Via: 1.1 varnish-v4
X-Varnish-Cache: MISS
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool: http_pages
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-Varnish-Hash: /data/action/getGame/9788578457657
X-Varnish-Backend-Ourself: arnish_server_snarf_foo_uk
X-DMG-Version: 6.20.51.2358
Accept-Ranges: none
Connection: keep-alive
第三次更新
所以在将http方法更改为OPTIONS
之后
$http(
方法:'选项',
...
我在 chrome 控制台中遇到了这个错误
XMLHttpRequest 无法加载 http://example.com/data/action/getGame/9788578457657。对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://dev.my-dev.local'' 不允许访问。响应的 HTTP 状态代码为 405。
这些是标题:
OPTIONS /data/action/getGame/9788578457657 HTTP/1.1
Host: example.com
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: OPTIONS
Origin: http://dev.my-dev.local/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36
Access-Control-Request-Headers:
Accept: */*
Referer: http://dev.my-dev.local//game/id-9788578457657
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
HTTP/1.1 405 Method Not Allowed
Date: Wed, 14 Dec 2016 16:52:03 GMT
Server: Varnish
X-Varnish: 6619151
X-Varnish-Trimen: www.trimen.com
X-Varnish-Served-By-Host: snarf.foo.uk
X-Varnish-Served-By-IP: 100.100.10.80
X-Varnish-Pool:
X-Varnish-Req-Backend-Hint: dead
X-Varnish-Req-Restarts: 0
X-DMG-Version: 6.20.51.2358
Content-Type: text/html; charset=utf-8
Retry-After: 5
Content-Length: 49669
Connection: keep-alive
【问题讨论】:
首先,您是否已经按照此处How can you debug a CORS request with cURL? 描述的方式尝试过(在标题中传递Origin:
)?因为标头 Vary: Accept-Encoding,Origin
告诉您,如果您将 Origin
与您的请求一起传递,则会得到不同的响应,并表明可能启用了 CORS。
@t.niese ,感谢您的提示。我更新了我的问题,但我看不出这个 curl 响应有什么真正的不同?
【参考方案1】:
您需要收到以下标头:
Access-Control-Allow-Origin: *
(或您想要限制的任何主机)
Access-Control-Allow-Methods: *
(或您想限制的任何方法)
Access-Control-Allow-Headers: Content-Type
注意最后一个也很重要,因为您正在设置Content-Type: application/json;charset=UTF-8
。如果您有任何其他自定义标题,您也需要添加它们。
这些都是在服务器上完成的,你的应用不需要做任何其他事情。
或者(如果可能)您可以选择完全不使用 application/json
,并将您的 Content-Type
设置为 application/x-www-form-urlencoded
、multipart/form-data
或 text/plain
,并且不会完成预检 (OPTIONS
) 请求并且在服务器上是否启用CORS
无关紧要。
【讨论】:
谢谢,您是说 API 服务器上不存在正确的 CORS 标头并且仍需要添加它们?如果这些标头存在,我的 AngularJS 应用程序上的内容应该足以获取 JSON 对象? 我从来没有使用过 cURL 来测试这个,所以我不确定。我没有看到那里的标题,但同时我没有看到任何确认您的请求是预检请求,即方法OPTIONS
,因此您的测试请求同样可能是错误的。在发出我想要工作的实际请求时,我通常只检查浏览器内的 chrome 开发工具。您将在那里看到预检请求,如果成功,则会在其后看到另一个单独的请求
如果预检,我如何检查我的请求?我在 Chrome 中禁用了相同的来源策略,并从 Chrome 的网络面板获取了我的 JSON 请求的标头,我用详细信息更新了我的问题。这有帮助吗?
用Method: OPTIONS
发送请求,现在说了3遍:p方法是请求方法,如POST,PUT,GET
最后一个应该是Access-Control-Allow-Headers
,那么解决方案就行了【参考方案2】:
ed 的回答启发了我的解决方案
您需要在预检请求期间发送以下标头(端点的 OPTIONS 方法)
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Origin, xxx
其中 xxx 是您在执行 POST/PUT/DELETE/etc 请求时发送的任何附加标头
请注意,当此解决方案有效时,我强烈建议更改 *
以将其限制为您已知的来源
【讨论】:
以上是关于CORS 已启用,但仍出现 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章
在带有 Angular 的 Spring Boot 中启用了 Cors,但仍然出现 cors 错误