浏览器中的CORS标头已更改,导致内容被阻止 [英] CORS Headers are altered in the browser resulting in content becoming blocked

查看:138
本文介绍了浏览器中的CORS标头已更改,导致内容被阻止的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新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

POST /dev/micro_server.php HTTP/1.1 Host: production-server.com
Connection: keep-alive
Content-Length: 86
Pragma: no-cache
Cache-Control: no-cache
Accept: text/html, /; q=0.01
Origin: https://debug.dev
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36 OPR/58.0.3135.90
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: https://debug.dev/
Accept-Encoding: gzip, deflate, br
Accept-Language: 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,OPTIONS
Access-Control-Allow-Origin: https://production-server.com
Access-Control-Allow-Credentials:true
过期:格林尼治标准时间1981年11月19日星期四08:52:00
缓存控制:不存储,不缓存,必须重新验证,后检查= 0,预检查= 0
语篇:无缓存
内容编码:gzip

HTTP/1.1 200 OK
Server: nginx/1.4.6 (Ubuntu)
Date: Tue, 12 Mar 2019 12:01:27 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.5.9-1ubuntu4.17
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: https://production-server.com
Access-Control-Allow-Credentials: true
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Encoding: gzip

控制台错误:

通过' https://production-server.com/dev/micro_server.php访问XMLHttpRequest "(源自来源" https://debug.dev ")已被CORS政策阻止:访问- "Control-Allow-Origin"标头的值" https://production-server.com "不相等到提供的原点.

Access to XMLHttpRequest at 'https://production-server.com/dev/micro_server.php' from origin 'https://debug.dev' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://production-server.com' that is not equal to the supplied origin.

控制台警告:

跨域读取阻止(CORB)阻止了跨域响应 https://daikai.no/dev /micro_server.php ,MIME类型为text/html.有关更多详细信息,请参见 https://www.chromestatus.com/feature/5629709824032768 .

Cross-Origin Read Blocking (CORB) blocked cross-origin response https://daikai.no/dev/micro_server.php with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.

从服务器的角度来看

这是服务器说已接收和发送的内容(请检查执行更新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:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin: https://production-server.com

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://production-server.com

但是,如果我右键单击并使用在新标签页中打开,则CORS标头应为原标题;即

But if I right click and use Open in new tab the CORS headers are what they ought to be; i.e.

Access-Control-Allow-Credentials:true
Access-Control-Allow-Origin: https://debug.dev

Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: https://debug.dev

据我所知,请求之间的唯一区别是,第一个请求是作为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?

推荐答案

问题可能与

未将服务器配置为使用正确的"Access-Control-Allow-"标头来响应OPTIONS请求.

The server is not configured to respond to OPTIONS requests with the correct "Access-Control-Allow-" headers.

在新标签页中打开网址是一个 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文档:

如果服务器指定的是单个来源而不是通配符"*",则服务器还应在Vary响应标头中包含Origin,以向客户端指示服务器响应将基于Origin请求标头的值而有所不同.

If the server specifies a single origin rather than the "*" wildcard, then the server should also include Origin in the Vary response header — to indicate to clients that server responses will differ based on the value of the Origin request header.

因此,还要设置 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;
}

参考文献

优先请求

禁止对飞行前403的响应

这篇关于浏览器中的CORS标头已更改,导致内容被阻止的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆