-1

几天前新的 Opera 65 出现了地址栏重新设计,我注意到我的网页上有一个问题。在栏中键入或复制地址时,Opera 会向服务器发送请求,但是,我无法在 PHP 中捕获请求,看起来,Fetch API 是在后台使用的。

有没有办法拒绝或阻止PHP 7 或 Apache 2.4 中的 Fetch API 请求?换句话说,在输入/复制时阻止 Opera 在服务器端产生的请求(首选 PHP)?

特别是,我需要排除在查询中提供带有哈希键的操作的 GET 请求(下面的示例中的测试)。当地址被复制(例如从邮件)到地址栏时,Opera“在后台”发送请求,请求被执行,但是在通过 Enter 提交地址后,第二个请求返回错误,因为禁止操作(哈希密钥不再有效)。

来自 Apache 日志:

127.0.0.1 - - [29/Nov/2019:01:56:08 +0100] "GET /? HTTP/1.1" 200 179736
127.0.0.1 - - [29/Nov/2019:01:56:08 +0100] "GET /?t HTTP/1.1" 200 179813
127.0.0.1 - - [29/Nov/2019:01:56:08 +0100] "GET /?te HTTP/1.1" 200 179808
127.0.0.1 - - [29/Nov/2019:01:56:08 +0100] "GET /?tes HTTP/1.1" 200 179819
127.0.0.1 - - [29/Nov/2019:01:56:08 +0100] "GET /?test HTTP/1.1" 200 179823

来自 Wireshark(请求之一):

/?test HTTP/1.1
Host: sk.localhost
Connection: keep-alive
Sec-Fetch-Site: none
Sec-Fetch-Mode: no-cors
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36 OPR/65.0.3467.48
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9

使用的技术:PHP 7.3.7、Apache/2.4.39

4

1 回答 1

0

Apache 重写条件或基于解析的标头的 PHP 响应可以拒绝(发送响应)请求。

Opera 在键入时发送两个 Fetch API 标头:

Sec-Fetch-Site: none
Sec-Fetch-Mode: no-cors

所有标头的列表可以在https://w3c.github.io/webappsec-fetch-metadata/找到。

要不为带有此标头的请求发送完整响应(不使用 PHP),您可以使用 Apache 2.4 mod rewrite 模块:

RewriteCond %{HTTP:Sec-Fetch-Site} ^none$ [NC]
RewriteCond %{HTTP:Sec-Fetch-Mode} ^no-cors$ [NC]
RewriteRule ^ - [R=204,L]

或通过 PHP 发送响应(使用 Kohana/Koseven FW 的示例):

    $header_sec_fetch_site = $this->request->headers('Sec-Fetch-Site');
    $header_sec_fetch_mode = $this->request->headers('Sec-Fetch-Mode');
    if (isset($header_sec_fetch_site, $header_sec_fetch_mode)
            && $header_sec_fetch_site == 'none'
            && $header_sec_fetch_mode == 'no-cors')
    {
        $message = 'Header ' . $header_sec_fetch_mode . ' received. No content for this request.';
        Log::instance()->add(Log::NOTICE, $message);
        throw HTTP_Exception::factory(204, $message, array(
                ':uri' => Request::current()->uri(),
            ));
    }

标头应该在全局变量中可用:

$_SERVER['HTTP_SEC_FETCH_DEST']
$_SERVER['HTTP_SEC_FETCH_SITE']
$_SERVER['HTTP_SEC_FETCH_USER']
$_SERVER['HTTP_SEC_FETCH_MODE']

于 2019-11-30T16:40:34.087 回答