前言
你们的博客网站有隔三岔五就收到这么多的垃圾评论吗?
这里所说的垃圾评论专指机器人通过自动化脚本或直接调用接口发起的评论,由于评论不经过前端页面,因此并不会给网站带来任何流量。说到垃圾评论,真的是非常恶心,如果仅仅是偶尔来一两条我都所谓,大不了隔段时间集中删一次,但实在架不住它短时间内狂轰乱炸,尤其是像我这样接入了邮件通知的,一旦开始,手机就响个不停,烦得要死。
下面就是这种评论,很明显名字和邮箱都是随机生成的,这种事情已经不知道发生过多少次了。
不过在之前由于发生的频率不算高,而且大部分时间我都是人在电脑旁,因此,随手就通过屏蔽IP解决了。
但最近的一次实在是忍无可忍了,因为它是大半夜开始轰炸的,半夜爬起来屏蔽IP成了最后的导火索,当时就想着第二天无论如何也要把这个问题给解决了。
1. 方案选择
直接关闭评论肯定是不行的,毕竟这是博客中唯一一个能和网友互动的入口了。只让登录用户评论?肯定也不行,至少我的博客网站还没有登录的价值。我的第一想法就是加上 图片验证码,其目的就是拦住机器人,放行真人,而且这个也最常用,现成的代码一大堆,复制过来改改就能用。但在具体实现的时候却发现了问题,图片处理需要安装并启用 GD
库,自己用也就罢了,但主题一旦依赖了 GD
库,别人用起来就麻烦了,因此就放弃了。
在寻找新方案的时候找到了这个 算术验证码 的方案,该方案比 图片验证码 更简单,就是让用户在提交评论之前进行一次 10 以内的加法计算,不需要额外的依赖,也不需要服务器缓存,更省服务器资源,如下图所示:
当然,该方案破解破解起来也很容易,但至少需要写程序,起码不能再随机生成内容就提交了。也就是说,通用的机器人工具应该是不能自动识别这种验证方式的。我当时的想法是,如果机器人能识别,我就换成减法,如果还能识别,我就换成字符串拼接或者直接让用户抄写一遍文本等等,总有一种简单的方式是机器人不支持的。当然,这么做的前提是没人闲的没事专门针对性的写破解脚本,我想也不会有,毕竟小小博客肯定不够格。
开发完成后,我观察了十几天,虽然还是会有一些零星的不确认是人工还是机器人发布的外语评论,但好像确实没有再发生垃圾评论轰炸的事了。
2. 具体实现
前面说了那么多,其实具体实现很简单,首先在 functions.php
文件中加入如下核心代码:
function themeInit($comment)
{
if ($comment->is('single')) {
$comment = spam_protection_pre($comment);
}
}
function spam_protection_math()
{
$user = Widget::widget(User::class);
if (!$user->hasLogin()) {
$num1 = rand(0, 9);
$num2 = rand(0, 9);
echo "<input type=\"text\" name=\"sum\" class=\"form-control\" value=\"\" size=\"8\" placeholder=\"$num1 + $num2 = ?\">\n";
echo "<input type=\"hidden\" name=\"num1\" value=\"$num1\">\n";
echo "<input type=\"hidden\" name=\"num2\" value=\"$num2\">";
}
}
function spam_protection_pre($commentdata)
{
$user = Widget::widget(User::class);
if (isset($_REQUEST['text']) && $_REQUEST['text'] != null && !$user->hasLogin()) {
$sum = $_POST['sum'];
switch ($sum) {
case null:
$commentdata->response->throwContent(_t('未输入验证码,请<a href="javascript:history.back()">返回上一页</a>重新输入。'));
break;
case $_POST['num1'] + $_POST['num2']:
break;
default:
$commentdata->response->throwContent(_t('验证码错误,请<a href="javascript:history.back()">返回上一页</a>重新输入。'));
}
}
return $commentdata;
}
然后,在 comments.php
文件中 form
表单内的适当位置加上 <?php spam_protection_math(); ?>
就可以了,具体加在哪里,这取决于你的页面结构和样式。
这段代码基本上所有 Typecho 主题都可以直接复制使用(样式除外),当然,这里如果做成无刷新评论,用户体验会更好,但是这样一来就不通用了,因此,先就这样吧,能用就行。
结语
该功能的源码我已经在 WaterDrop 和 BeaconNav 两个主题中都更新了,有同样困扰的同学可以试一下。我是观察了一段时间后才写的这篇文章,目前感觉应该是有效的,当然,如果后续发现失效了,大不了再换一种方式就是了。
评论2
CF673X
还有短代码 需要如何加载上去
CF673X
请教一下 宽屏是需要如何调试。