WordPress垃圾评论大作战

自从把博客搬到独立服务器之后,垃圾评论有日益增长的趋势。

上次集中清理垃圾评论的时间,刚好是6月初的一天。到8月下旬,居然积攒了5000多条垃圾评论!

WordPress的用户应该都深有感触,这个博客程序还是挺招惹垃圾评论的。因此WordPress自带了一个叫Akismet的插件。

Akismet插件工作原理是,将垃圾评论通过API上报到云端(想当年,Akismet诞生时云还不叫云,叫远程服务器),然后也会把垃圾评论存到垃圾评论数据库中。

不过像我这样几个月收几千条垃圾评论的用户来说,存起来显然不是个好办法。那么,怎么解决呢?

不急不急,解决之前,不如先分析一下问题吧!

垃圾评论也分三六九等的,定义如下:

  1. 机器人瞎子一样直接向WordPress的评论接口发数据包
  2. 机器人先解析页面,然后构造请求
  3. 机器人解析页面,还模拟浏览器运行脚本,然后构造请求
  4. 人工手打垃圾评论

分析了几千条垃圾评论,我觉得,像我这种小博客,99.99%都是第一、第二种情况。第三种几乎没有。第四种的话……也太看得起本站了。

分析之后,豁然开朗,针对第一种的情况,其实只需要在页面加一些隐含的字段就可以了。不过现在的机器人似乎比较聪明,还是会看一下评论表单的隐藏字段。那么就用脚本再加另外一个隐含字段——只有运行脚本的浏览器,才能正确解析,也才能正确发送这一个由脚本填充的隐藏字段。

但是,这种方案也有缺点,如果用户的浏览器不支持脚本,也就无法正确发送脚本填充的隐藏字段,同样会被拦截。关键在于,这样的用户有多少呢?

这时候,大数据(误)就派上用场了。我看了一下来访用户统计,大部分都是chrome或chrome核心,其它移动端的用户也是智能设备。也就是说,感谢科技发展,大部分用户的浏览器都是支持脚本的。那么,这个措施还是可以实施的。

于是乎,总结上面啰啰嗦嗦的一大串文字结论如下:

  1. 使用脚本在评论表单添加隐藏字段,发表评论时验证字段。
  2. 其余漏网之鱼,交给Akismet拦截。

参考代码如下:

<?php

defined( 'ABSPATH' ) or die( 'No script kiddies please!' );

define('DEFAULT_JQUERY_BEFORE', 'jQuery(function($) {');
define('DEFAULT_JQUERY_AFTER', '});');

function creke_cal_comment_val($k)
{
return strval(crc32('CrekeComment'.$k));
}

function creke_get_comment_form()
{
if(is_user_logged_in())
{
return;
}

$k = time(NULL);
$v = creke_cal_comment_val($k);
return "
<input type='hidden' name='creke_comment_k' value='$k' />
<input type='hidden' name='creke_comment_v' id='creke_comment_v' creke_comment_v='$v' value='$k'/>
";
}

function creke_get_comment_script($jQueryBefore=DEFAULT_JQUERY_BEFORE, $jQueryAfter=DEFAULT_JQUERY_AFTER)
{
if(is_user_logged_in())
{
return;
}

return "
<script type='text/javascript'>
$jQueryBefore
var id='#creke_';
id+='comment_v';
$(id).val($(id).attr('creke_comment_v'));
$jQueryAfter
</script>
";
}

function creke_comment_form()
{
echo creke_get_comment_form();
echo creke_get_comment_script();
}

add_action('comment_form', 'creke_comment_form');

function creke_comment_check($commentdata)
{
$dieMsg = 'do not spam';
$dieTitle = 'title';
$isSpam = FALSE;

$type = comment_type('comment', 'trackback', 'pingback');

if(is_user_logged_in() || $type == 'pingback' || $type == 'trackback')
{
return $commentdata;
}

$k = $_POST['creke_comment_k'];
$v = $_POST['creke_comment_v'];
if((time(NULL) - $k) > 86400)
{
$isSpam = true;
}
if(!$isSpam)
{
$isSpam = (creke_cal_comment_val($k) != $v);
}

if($isSpam)
{
wp_die($dieMsg, $dieTitle);
}

return $commentdata;
}

if(!is_admin()) {
add_filter('preprocess_comment', 'creke_comment_check', 1);
}

?>

7 comments

  1. Michael says:

    挺有意思的文章,内容妙趣横生。
    其实 Akismet 挺够用的,除了手打的,基本都能挡住。
    遇到狂刷的那种,直接把他们段给封掉了,哈哈。

    1. creke says:

      我遇到的基本都是狂刷的……封IP太麻烦,还是自己动手比较好哈哈
      PS:谢谢支持~

  2. 静静 says:

    窝发现加了HTTPS貌似会无视辣鸡评论?

    1. creke says:

      你的辣鸡评论即将升级支持https→_→

  3. 珐琅珠宝 says:

    一入码农深似海,大神加油

    1. creke says:

      你这是手动留言的么→_→

  4. AFX says:

    破站根本不敢开评论的路过←(晚八点前发每条五毛删掉括号

Leave a comment