更新2(完整的日志集)
POST /dev/micro_server.php HTTP / 1.1 主持人:production-server.com
连接:保持活动状态
内容长度:86
语法:无缓存
缓存控制:无缓存
接受:text / 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; charset = 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 GMT
内容类型:text / html
传输编码:分块
连接:保持活动状态
X-Powered-By:PHP / 5.5.9-1ubuntu4.17
访问控制允许方法:GET,POST,选项
访问控制允许来源:https://production-server.com
访问控制允许凭据:true
过期:格林尼治标准时间1981年11月19日星期四08:52:00
缓存控制:不存储,不缓存,必须重新验证,后检查= 0,预检查= 0
语法:无缓存
内容编码:gzip
CORS策略已阻止从源“ https://production-server.com/dev/micro_server.php”访问“ https://debug.dev”处的XMLHttpRequest:“ 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://production.com
更改为Access-Control-Allow-Origin: https://debug.dev
?
(原始帖子)
背景
我有一个基于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请求时,我得到了服务器域的错误 CORS标头:
Access-Control-Allow-Credentials:true
访问控制允许来源:https://production-server.com
但是,如果我右键单击并使用在新标签页中打开,则CORS标头应为原标题;即
Access-Control-Allow-Credentials:true
访问控制允许来源:https://debug.dev
据我所知,请求之间的唯一区别是,第一个请求是作为AJAX POST请求发送的,因此发送的是HTTP_X_REQUESTED_WITH标头,而第二个请求是作为普通的GET请求发送的。服务器如何返回不同的CORS标头?
答案 0 :(得分:3)
问题可能类似于my answer here:
服务器未配置为使用正确的“ Access-Control-Allow-”标头来响应OPTIONS请求。
在新标签页中打开网址是一个 GET 请求,并且正在运行,因为它满足要求时未发出预检请求由simple request
定义为CORS documentation的条件另一方面, ajax请求是一个 POST 请求,并且满足成为Preflighted request的条件,这意味着 preflight OPTIONS请求应该先做。
简而言之,您已经正确设置了CORS响应标头,但是服务器未配置为添加这些标头用于OPTIONS方法请求。
解决方案是使用 2xx响应处理服务器代码上的选项请求,并添加** Access-Control-Allow-就像您处理GET和POST请求一样。请记住,OPTIONS请求不包含任何参数,因此应在任何验证或请求解析之前完成。
此外,根据Access-Control-Allow-Origin documentation:
如果服务器指定单个来源而不是通配符“ *”,则服务器还应在Vary响应标头中包含Origin -向客户端指示服务器响应将基于Origin请求标头的值而有所不同。
因此,还要设置 Var 响应标头:
例如在脚本顶部尝试:
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;
}
答案 1 :(得分:1)
问题是您使用了header("Access-Control-Allow-Origin: " . $_SERVER['HTTP_ORIGIN']);
(顺便说一句,不建议这样做),并且标题错误。我打赌原因之一:
让我们从头开始。
您是否知道您使用的构造与Access-Control-Allow-Origin: *
是同义词?您应该检查HTTP_ORIGIN
是否属于允许的池。