不用插件屏蔽 WordPress 垃圾评论

最近对博客评论功能做了一些调整,防垃圾评论便是其一。即便作为一个无名小站每天也会收到几条垃圾评论,这之前一直用 Akismet 插件来防垃圾评论,Akismet 好是好,只是太臃肿,另外,阻止下来的垃圾评论仍需要手动清理,久而久之快要被动地锻炼成定期查看垃圾评论的强迫症了,便想着如何换掉 Akismet。

搜集了一些关于 WordPress 垃圾邮件工作机制介绍的资料,一般认为垃圾评论是通过机器发送了,机器会向id="comment"name="comment"的文本框填充评论内容,再提交给 wp-comments-post.php 文件。

于是,想到可不可以做一个取巧的方法:

  1. 评论表单默认的comment文本框专门留给机器用,并通过display:none将之隐藏;
  2. 增加一个额外的文本框(如blog_audience)留给真正的访客;
  3. 评论提交的时候做判断:干掉comment不为空的,comment为空则把给真正访客准备的文本框取为comment_content并完成后续处理。

改造评论表单

这个主题评论框用的是<?php comment_form(); ?>(一般是在主题文件夹的 comments.php 文件里),加额外字段需要对comment_form()做处理。

添加额外文本框

总之,把要加的额外的文本框

<textarea id="blog_audience" name="blog_audience" class=" comment-textarea"></textarea>

加入之后得到如下代码:

<?php comment_form( array(
            'fields' => array(
                'author' => '<p class="commentform"><input type="text" name="author" id="author" class="ipt cmt-input" placeholder="昵称" aria-required="true" size="30" value="' . esc_attr( $commenter['comment_author'] ) . '"></p>',
                'email' => '<p class="commentform"><input type="text" name="email" id="email" class="ipt cmt-input" placeholder="邮箱[保密]" aria-required="true" size="30" value="' . esc_attr( $commenter['comment_author_email'] ) . '"></p>',
                'url' => '<p class="commentform"><input type="text" name="url" id="url" class="ipt cmt-input" placeholder="网址[可不填]" size="30" value="'.$comment_author_url.'"></p>'
                ),
            'comment_field' => '<p><textarea id="comment" name="comment"></textarea></p>
            <p><textarea id="blog_audience" name="blog_audience" class="ipt comment-textarea" placeholder="添加评论..." aria-required="true" cols="45" rows="8"></textarea></p>',
            'comment_notes_before' => '',
            'comment_notes_after' => '',
            'action' => '/stop-spam.php',
            'class_submit' => 'submit'
        ));
    ?>

替换表单 action

下一步需要对 wp-comments-post.php 做修改,考虑到 WordPress 版本更新覆盖旧文件问题,最好不要直接改动 wp-comments-post.php 文件,建议在博客根目录(wp-comments-post.php 所在的文件夹)新建一个单独的文件做跳板,如:stop-spam.php,comment_form()默认的action是 wp-comments-post.php,现在要把action改为 stop-spam.php,只需将'action' => '/stop-spam.php',放到上面代码'class_submit' => 'submit'的前一行即可。

跳板文件

接下来打开 stop-spam.php,把下面代码放入并保存:

<?php
$comment = trim($_POST['comment']);
// Proceed with regular comments.
if ( empty( $comment ) ) {
    $_POST['comment'] = trim($_POST['blog_audience']);
    require( dirname(__FILE__) . '/wp-comments-post.php' );
}
if ( ! empty( $comment ) ) {
    require( dirname(__FILE__) . '/wp-load.php' );
    nocache_headers();
    wp_die('You are not a human!');
}

大功告成,一旦 stop-spam.php 收到提交上来的表单,即会检查comment文本框是否为空,有内容即认为是机器填写的(comment文本框做了隐藏后正常人是看不到的),直接终止并给一个错误提示。

如果为空,则认为是正常访客提交的(正常访客只会在他们看到的blog_audience文本框内填写评论内容,而机器只会找comment),进而将blog_audience文本框中的内容取作评论内容,接下来再将数据传递给 wp-comments-post.php 进行后续处理,换句话说就是中间做一次劫持替换。

禁止直接访问 wp-comments-post.php

如果还是不放心,那就直接禁掉 wp-comments-post.php 文件的正常访问,这个博客搭建在 nginx 上,把下面这段代码加入到 nginx 的主机配置文件重启 nginx 即可实现禁止直接访问 wp-comments-post.php 文件(不影响 stop-spam.php 文件 require 它)。

location ~ /(\.wp-comments-post\.php) {
    return 404;
}

用了两周效果很不错,没有一条垃圾评论!

以上方法只对通过 wp-comment-post.php 提交的常规垃圾评论有效,但往往很多垃圾评论是通过 trackback 形式发生的,如需屏蔽 trackback 请参照如何屏蔽 trackback/pingback 垃圾评论

发表评论

评论(11)

  1. Pingback屏蔽 trackback/pingback 垃圾评论 – 木瓜园
  2. 姜辰

    不怕机器,就怕人为的

    1. Shrek

      @姜辰 人为的真没办法,手工垃圾评论只能指望 Akismet

      1. 姜辰

        @Shrek 我现在是关键词拉黑的模式

        1. Shrek

          @姜辰 关键词局限性太大了。

          1. 姜辰

            @Shrek 关键词是他们的网址,如果他们无法提交网址,呢么所做的垃圾评论也是~~你懂得~

            1. Shrek

              @姜辰 懂了

  3. 老杨

    方法有点类似 https://leonax.net/p/6732/block-spam-comments-from-web-page/。不过,感觉其实加了 ajax 提交评论,然后禁止访问 wp-comments-post.php 文件,就能挡住绝大部分的垃圾评论了。

    1. Shrek

      @老杨 他这个功能更高级

  4. 大致

    过两天参考参考你的,加到我的新主题上。
    其实机器怎么都好防。人肉就难了。

    1. Shrek

      @大致 这个方法只能防常规的垃圾评论,防不了 trackback 过来的垃圾评论,如果要试最好留着 akismet,另外又整了一个防 trackback 的方法,就等着今晚来 trackback 测试了。