我想阻止对我的网站重复发出的相同请求。例如,某人点击“刷新”按钮 3 次,因此我希望自动阻止该用户发出的相同请求。
我知道我可以使用 PHP 或任何服务器端编程语言来实现这一点,但是是否有独立于网站的“可移植”解决方案,例如 Apache2 配置或 iptables 规则?
还有其他这种基本的保护方法吗?
答案1
我很确定,如果你能设法在 iptables 中实现这一点,那将是一个非常糟糕的主意。iptables 理解网络的第 3 层和第 4 层OSI 模型;HTTP 请求位于第 7 层。
由于 HTTP 是一种无状态协议,而您尝试根据当前状态给出不同的响应,因此您需要某种方法来跟踪状态。通常的做法是使用 cookie,尽管这不是跟踪状态的唯一方法。 mod_rewrite
能够设置和读取 cookie 并将其与正则表达式匹配,因此我们首先尝试一下。
你可以使用以下规则来任何页面请求太快,无法被阻止:
RewriteRule (\.html|\.php)$ - [CO=recent:true:example.com:1:/]
RewriteCond %{HTTP_COOKIE} recent=true
RewriteRule (\.html|\.php)$ - [F]
.html
第一条规则会为每个或页面设置一个 cookie,.php
其有效期为一分钟。下一对或规则会导致任何带有该 cookie 的.php
或.html
页面的请求(即一分钟内)被拒绝。一分钟后,cookie应该已过期并且不再发送。
这里存在一些缺点:它不限制自己使用相同的 URL,因此每个页面请求都必须在前一个请求之后一分钟,并且到期时间以分钟为单位,因此一分钟是最短的时间。您只能收到 403 个响应,这些响应不一定非常友好或信息丰富。这是我使用 Apache 所能做到的最好程度。nginx 具有更像编程的配置语言,它可能允许您进行 URI 比较,以便仅阻止页面刷新而不阻止其他请求。
使用 PHP(或其他任何语言)将当前 URL 和时间戳放入会话中(或将 IP 地址和源端口与当前 URL 和时间戳一起存储在数据库中。如果您的客户端不支持 cookie,则可以这样做。)将允许您进行比较。如果当前 URL 和会话中的 URL 相同,并且时间戳在当前时间的某个阈值内,则可以向他们发送不同的响应。使用 PHP(而不是 Apache),您可以发送 503 响应(这更有意义),并附上一些适当的文本来解释为什么他们得到的是该响应而不是他们期望的页面。
我认为最好的选择是 Javascript 和/或键绑定。绑定执行刷新的键(Mac 上的 Cmd + R,任何地方的 Ctrl + R、F5),以便您可以拦截它们并使用 Javascript 建议用户在点击刷新之前等待一段时间。此选项具有最佳的用户体验,并且对服务器的影响最小。