拒绝来自 Opera 地址栏的服务器端(PHP 或 Apache)的 Fetch API 请求

Posted

技术标签:

【中文标题】拒绝来自 Opera 地址栏的服务器端(PHP 或 Apache)的 Fetch API 请求【英文标题】:Deny Fetch API requests on server side (PHP or Apache) from Opera address bar 【发布时间】:2020-03-24 15:17:00 【问题描述】:

由于几天前带有address bar redesign 的新Opera 65 发布,我注意到我的网页上存在问题。 在栏中键入或复制地址时,Opera 会向服务器发送请求,但是,我无法在 php 中捕获请求,因为似乎在后台使用了 Fetch API。

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

特别是,我需要排除在查询中提供带有 散列键 操作的 GET 请求(以下示例中的 test)。 当地址被复制(例如从邮件)到地址栏时,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

【问题讨论】:

哇。你确定你没有靠在你的“输入”键上吗?如果 Opera 不认为这种行为是一个错误,我想我会阻止 Opera 用户代理。想想我的flabbers彻底吓坏了 还有GET请求定义的角度应该是幂等的。如果请求正在更改状态,则它应该是 POSTPUTPATCH 或 what-have-you。 我很确定。每次在查询中键入字母时都会发送请求。它不会改变我的要求 - 拒绝此类请求。 你在这里没有多大意义。一个请求就是一个请求——无论它是使用 Fetch 还是其他任何东西发出的,都应该与您在服务器端基本处理它的方式高度无关。 “我无法在 PHP 中捕获请求” - 那么您实际尝试过什么?由于此处的路径只是/,因此您必须在负责处理您的网站“根”文档的任何脚本中处理这个问题。可能只是主文件夹中的 index.php,也可能是其他东西,如果您使用的是某种实际的路由器…… 我不认为这是 Opera 有意实现的 - 猜测它要么是错误,要么是配置错误。根据用户输入的内容发送这样的请求对于获取搜索结果预览是有意义的,许多网站/服务(谷歌、***……)提供特定的 URL 来请求此类数据以进行“预输入预测”。 【参考方案1】:

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

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

Sec-Fetch-Site:无 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']

【讨论】:

以上是关于拒绝来自 Opera 地址栏的服务器端(PHP 或 Apache)的 Fetch API 请求的主要内容,如果未能解决你的问题,请参考以下文章

如何使用过滤器限制来自地址栏的所有请求

用opera快捷键搜索internet

ACL(访问控制列表)的分类和作用?

php开发中怎么获取服务端MAC地址?

sql 数据库拒绝访问

更改状态栏的颜色 [重复]