问题描述
更新2(完整的日志集)
响应标头:
控制台错误:
控制台警告:
从服务器的角度来看
这是服务器说已接收和发送的内容(请检查执行更新1记录的代码):
From Server's Perspective
This is what the server says it has received and sent (check the code that does the logging in update 1):
Array
(
[req] => Array
(
...
[HTTP_ORIGIN] => https://debug.dev
...
)
[rsp] => Array
(
[0] => X-Powered-By: PHP/5.5.9-1ubuntu4.17
[1] => Access-Control-Allow-Origin: https://debug.dev
[2] => Access-Control-Allow-Methods: GET, POST, OPTIONS
[3] => Access-Control-Allow-Credentials: true
)
)
更新
我已经在服务器上添加了一些日志,脚本现在从以下几行开始:
I have added some logging on the server and the script now begins with these lines:
# allow access from other domains
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Credentials: true");
$all = [
'req' => $_SERVER,
'rsp' => headers_list()
];
$s = print_r($all, true);
$p = '/var/www/path/to/file_' . uniqid() . '.txt';
file_put_contents($p, $s);
这样,我可以确认请求以正确的Origin到达服务器,并且服务器发送回正确的CORS标头.但是,开发者控制台中的Access-Control-Allow-Origin
是错误的,请求已被阻止.
With this I can confirm that the request arrives on the server with the correct Origin, AND the server sends back the correct CORS headers. Yet, the Access-Control-Allow-Origin
in the developer console is wrong and the request is blocked.
以下是通过上面的代码获得的精简日志:
Here is a stripped down log obtained with the code above:
Array
(
[req] => Array
(
...
[HTTP_ORIGIN] => https://debug.dev
...
)
[rsp] => Array
(
[0] => X-Powered-By: PHP/5.5.9-1ubuntu4.17
[1] => Access-Control-Allow-Origin: https://debug.dev
[2] => Access-Control-Allow-Methods: GET, POST, OPTIONS
[3] => Access-Control-Allow-Credentials: true
)
)
问题
当收到的实际标头为Access-Control-Allow-Origin: https://debug.dev
时,如何以及为何将Access-Control-Allow-Origin
更改为https://production.com
?
How and why does the Access-Control-Allow-Origin
is changed to https://production.com
when the actual header received is Access-Control-Allow-Origin: https://debug.dev
?
(原始帖子)
背景
我有一个基于Web的调试工具,已将其安装在本地开发计算机上.在/etc/hosts中的一个条目中,我已将其分配给域debug.dev
.我还添加了本地CA权限,并已成功为域名创建了SSL证书,因此现在我可以在浏览器中打开https://debug.dev/
,调试工具将正常打开.
I have a web-based debug tool that I have installed on my local development machine. With an entry in my /etc/hosts I have assigned to it the domain debug.dev
. I have also added a local CA authority and have successfully created a SSL certificate for the domain name so now I can open https://debug.dev/
in my browser and the debug tool opens normally.
该工具应该与登台服务器和生产服务器一起使用.因此,它需要将AJAX请求发送到其他域.我对这些服务器拥有完全控制权,并且正在从这些服务器发送回CORS标头,如下所示:
This tool is supposed to work with staging and production servers. So it needs to send AJAX requests to other domains. I have full control over those servers and I am sending back CORS headers from those servers like so:
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Credentials: true");
问题
现在,我面临着莫名其妙的局面,当我向生产服务器发送AJAX请求时,我得到了服务器域的错误 CORS标头:
Now I am facing a baffling situation in which when I send an AJAX request to the production server I get back Wrong CORS headers with the SERVER's domain like this:
但是,如果我右键单击并使用在新标签页中打开,则CORS标头应为原标题;即
But if I right click and use Open in new tab the CORS headers are what they ought to be; i.e.
据我所知,请求之间的唯一区别是,第一个请求是作为AJAX POST请求发送的,因此发送的是HTTP_X_REQUESTED_WITH标头,而第二个请求是作为普通的GET请求发送的.服务器如何返回不同的CORS标头?
The only differences between the requests as far as I can see is that the first one is sent as an AJAX POST request and thus sends a HTTP_X_REQUESTED_WITH header whereas the second request is sent as an ordinary GET request. How could this result in a different CORS header be returned by the server?
推荐答案
问题可能与:
在新标签页中打开网址是一个 GET 请求,并且正在运行,因为它满足要求时未发出预检请求成为简单请求的标准, CORS文档
Opening the url in a new Tab is a GET request and is working because it is not making a preflight request, as it meets the criteria to be a simple request as defined by the CORS documentation
另一方面, ajax请求是一个 POST 请求,并且满足成为已取消请求,这意味着应首先发出预检选项请求.
On the other hand, the ajax request is a POST request and meets the criteria to be a Preflighted request, meaning a preflight OPTIONS request should be made first.
简而言之,您已经正确设置了CORS响应标头,但是未将服务器配置为添加这些标头用于OPTIONS方法请求.
In short, you have correctly setup the CORS response headers, but the server is not configured to add these headers for OPTIONS method requests.
解决方案是使用 2xx响应处理服务器代码上的选项请求,并添加** Access-Control-Allow-就像您处理GET和POST请求一样.请记住,OPTIONS请求不包含任何参数,因此应在进行任何验证或请求解析之前完成.
The solution is to handle OPTIONS requests on the server code with a 2xx response and add the **Access-Control-Allow- as you do for GET and POST requests. Keep in mind that OPTIONS requests do not include any parameters, so this should be done before any validation or request parsing.
此外,根据访问权限-Control-Allow-Origin文档:
因此,还要设置 Var 响应标头:
So set the Vary response header also:
例如在您脚本的顶部尝试:
eg at the top of you script try:
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
header("Access-Control-Allow-Credentials: true");
header("Vary: Origin");
exit;
}
参考文献
这篇关于浏览器中的CORS标头已更改,导致内容被阻止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!