kavalar/botobor

PHP反垃圾邮件库

dev-master 2019-10-30 08:58 UTC

This package is auto-updated.

Last update: 2024-08-29 05:18:38 UTC


README

Build Status

[ 主页 ] [ API 文档 ]

工作原理

目前最常用的保护网页表单免受机器人攻击的方法是让用户证明自己是人类,通过执行机器人难以执行的动作(例如CAPTCHA)。但这在用户体验方面并不好。因为这样我们让用户执行了一些他们不需要且有时复杂的操作。

Ned Batchelder 提出了一个不同的思路。与其让我们的用户费劲地解析,不如让机器人暴露自己。关于这个主题,他有一篇详细的文章 通过散列和蜜罐阻止垃圾邮件机器人

Botobor 是一个 PHP 库,实现了 Ned 的想法。目前使用以下检查(任何一种都可以禁用)

  • 表单创建与提交之间时间过短;
  • 表单创建与提交之间时间过长;
  • 至少有一项诱饵字段被填写(见下文);
  • REFERER 头部与表单所在地址不匹配。

有人可能会说:“哎呀,这很简单!”。当然,确实如此。但 Botobor 的目标并不是绝对的保护(这也是不可能的)。Botobor 的目标更实际——减少机器人填写表单的可能性,同时不干扰真实用户。顺便说一下,Botobor 和 CAPTCHA 可以一起使用:Botobor 作为第一道防线,CAPTCHA 作为第二道防线,以防对用户的真实性有疑问。关于这一点,下面会详细说明。

安装

首先,您可以简单地下载 botobor.php 文件,并以任何您方便的方式将其连接到您的项目中。

其次,您可以使用 composer

php composer.phar require mekras/botobor:~0.4.0

使用

简单示例

创建表单的 PHP 代码

<?php
require 'path/to/botobor.php';
...
// Получите разметку формы тем способом, который предусмотрен у вас в проекте, например:
$html = $form->getHTML();
// Создайте объект-обёртку:
$bform = new Botobor_Form($html);
// Получите новую разметку формы
$html = $bform->getCode();

处理表单的 PHP 代码

<?php
require 'path/to/botobor.php';
...
if (Botobor_Keeper::get()->isRobot())
{
    // Форма отправлена роботом, выводим сообщение об ошибке.
}

带有选项的示例

您可以通过选项来更改 Botobor 的行为。例如,对于评论表单,增加参数 lifetime(表单创建和提交之间的最大时间间隔)是有意义的,因为访问者在评论之前可能会长时间阅读文章。

可以这样操作

<?php
$bform = new Botobor_Form($html);
$bform->setLifetime(60); // 60 минут

有关选项的详细信息,请参阅API 文档中关于 setChecksetDelaysetLifetime 方法的描述。

带有诱饵的示例

诱饵字段旨在捕获能够自行找到表单的机器人蜘蛛。这类机器人通常会在表单中寻找熟悉的字段(例如 name)并填写它们。Botobor 可以在表单中添加人类看不到(通过 CSS)的字段,并使用这些名称。人类将留下这些字段为空(因为他们看不到),而机器人则会填写,从而暴露自己。

在这个例子中,将“name”字段作为诱饵。此时,实际的“name”字段的名称将被替换为随机值。在调用 Botobor_Keeper::handleRequest 方法时(在 Botobor_Keeper::isRobot 中自动调用)将执行反向转换。

$bform = new Botobor_Form($html);
$bform->setHoneypot('name');

定义失败的检查

有时可能需要了解为什么Botobor判定访问者是机器人,访问者未通过哪种检查。可以使用方法Botobor_Keeper::getFailedCheck()来获取未通过检查的名称。检查的名称在API文档中有说明。

与CAPTCHA的联合使用

Botobor可以与CAPTCHA一起使用。一种可能的方案是:如果Botobor的检查显示表单是由机器人填写的,可以像Yandex在类似情况下做的那样,要求输入图片中的验证码。在代码中可能看起来像这样

<?php
function checkRequest()
{
    // Проверяем, использовался ли CAPTCHA в этом запросе
    if ($someCaptcha->isUsedInThisRequest())
    {
        /*
         * Попадание сюда говорит о том, что посетитель уже проходил, но не прошёл проверку
         * Ботобором и сейчас проходит проверку CAPTCHA. По итогам этой проверки мы либо признаём в
         * посетителе человека, либо окончательно отказываем ему.
         */
         if (!$someCaptcha->isPassed())
         {
             $this->showErrorNotify();
         }
    }
    elseif (Botobor_Keeper::get()->isRobot())
    {
        /*
         * Попадание сюда горовит о том, что посетитель не прошёл проверку Ботобором. На случай если
         * это было ложное срабатывание, мы дадим посетителю возможность пройти CAPTCHA, чтобы
         * доказать, что он не робот.
         */
         $this->showCaptcha();
    }

    // Посетитель — человек, можно обрабатывать его запрос
    $this->processRequest();
}