【发布时间】:2019-07-29 01:07:36
【问题描述】:
Update 2(完整的日志集)
从客户的角度来看
请求头:
POST /dev/micro_server.php HTTP/1.1 主机:production-server.com
连接:保持活动
内容长度:86
编译指示:无缓存
缓存控制:无缓存
接受:文本/html,/; q=0.01
来源:https://debug.dev
用户代理:Mozilla/5.0(X11;Linux x86_64) AppleWebKit/537.36(KHTML,如 Gecko)Chrome/71.0.3578.98 Safari/537.36 OPR/58.0.3135.90
内容类型:application/x-www-form-urlencoded;字符集=UTF-8
推荐人:https://debug.dev/
接受编码:gzip、deflate、br
接受语言:en-US,en;q=0.9
Cookie:debugger_session=iq4tbdk374mtvodsd3edcf2jq5
响应头:
HTTP/1.1 200 正常
服务器:nginx/1.4.6 (Ubuntu)
日期:格林威治标准时间 2019 年 3 月 12 日星期二 12:01:27
内容类型:text/html
传输编码:分块
连接:保持活动
X-Powered-By:PHP/5.5.9-1ubuntu4.17
访问控制允许方法:GET、POST、OPTIONS
访问控制允许来源:https://production-server.com
访问控制允许凭据:true
过期:1981 年 11 月 19 日星期四 08:52:00 GMT
缓存控制:无存储、无缓存、必须重新验证、后检查=0、预检查=0
编译指示:无缓存
内容编码:gzip
控制台错误:
从源“https://debug.dev”访问“https://production-server.com/dev/micro_server.php”处的 XMLHttpRequest 已被 CORS 策略阻止:“Access-Control-Allow-Origin”标头的值“https://production-server.com”不等于提供的原产地。
控制台警告:
跨域读取阻止 (CORB) 阻止了 MIME 类型为 text/html 的跨域响应 https://daikai.no/dev/micro_server.php。详情请见https://www.chromestatus.com/feature/5629709824032768。
从服务器的角度来看
这是服务器所说的它已接收和发送的内容(检查执行登录更新 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
)
)
更新
我在服务器上添加了一些日志记录,脚本现在以这些行开头:
# 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是错误的,请求被阻塞了。
这是使用上述代码获得的精简日志:
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?
(原帖)
背景
我在本地开发机器上安装了一个基于 Web 的调试工具。在我的 /etc/hosts 中有一个条目,我已经为它分配了域 debug.dev。我还添加了本地 CA 机构,并成功为域名创建了 SSL 证书,所以现在我可以在浏览器中打开 https://debug.dev/ 并且调试工具正常打开。
这个工具应该适用于登台和生产服务器。所以它需要向其他域发送 AJAX 请求。我可以完全控制这些服务器,并且我正在从这些服务器发回 CORS 标头,如下所示:
header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
header("Access-Control-Allow-Credentials: true");
问题
现在我面临一个莫名其妙的情况,当我向生产服务器发送 AJAX 请求时,我得到了 Wrong 带有 SERVER 域的 CORS 标头,如下所示:
访问控制允许凭据:true
访问控制允许来源:https://production-server.com
但是,如果我右键单击并使用 在新选项卡中打开,CORS 标头就是它们应该是的;即
访问控制允许凭据:true
访问控制允许来源:https://debug.dev
据我所知,请求之间的唯一区别是第一个请求作为 AJAX POST 请求发送,因此发送 HTTP_X_REQUESTED_WITH 标头,而第二个请求作为普通 GET 请求发送。这会导致服务器返回不同的 CORS 标头吗?
【问题讨论】:
-
还提供浏览器控制台的完整输出。 (也启用
info消息)还显示所有发送和接收的 OPTIONS 请求标头。 -
很可能没有足够的信息来回答这个问题......例如。错误的服务器提供的页面(拔下电缆,它可能无法访问)。一个快速而肮脏的解决方法是在同一个标题中返回两个主机名......或者只是使用
xdebug进入它。 -
我被束缚住了,没能早点回答。 @Soleil,不,它们在不同的机器上。 debug.dev 位于本地计算机 (127.0.0.1) 上,production-server.com 是 Digitalocean 液滴。
-
@MartinZeitler 所有证据,包括登录 production-server.com 都表明服务器正在发送正确的标头。在接收端,虽然我们得到了 Origin 标头的不同值。我会尽量让问题更清楚。
-
@MajidFouladpour 日志记录不一定确认请求命中此实例(除非记录时间戳和 IP)。虽然在那里设置断点肯定会。客户端应该如何重写标头的值......甚至不知道其他主机名?在整个代码库中搜索
header和硬编码的主机名可能也是我会尝试的,因为理论上可以覆盖标头的值。