最近对博客评论功能做了一些调整,防垃圾评论便是其一。即便作为一个无名小站每天也会收到几条垃圾评论,这之前一直用 Akismet 插件来防垃圾评论,Akismet 阻止下来的垃圾评论仍需要手动清理,久而久之快要被动地锻炼成定期查看垃圾评论的强迫症了,便想着要换掉 Akismet。
搜集了一些关于 WordPress 垃圾邮件工作机制介绍的资料,一般情况下垃圾评论是通过机器发送了,机器会向id="comment"
或name="comment"
的文本框填充垃圾评论内容,并直接提交给 wp-comments-post.php 文件生成评论。
既如此,可不可以用一个取巧的办法:
- 将评论表单默认的
comment
文本框通过display:none
隐藏掉(或者直接移除之); - 单独增加一个对访客可见的替代文本框,取名为
real_comment
,用户在页面填写的评论内容实际是放在real_comment
文本框的; - 由于 WordPress 通过
comment
文本框取评论内容,所以,在评论提交给 wp-comments-post.php 前需要判断处理一下:comment
文本框不为空,说明是垃圾邮件,直接返回错误就行了;comment
文本框为空,说明是用户填写的,提交前需要进行一次置换,即把comment_content
文本框的内容填充到comment
文本框,完成置换后再进行提交。
改造评论表单
这个主题评论框用的是<?php comment_form(); ?>
(一般是在主题文件夹的 comments.php 文件里),加额外字段需要对comment_form()
做处理。
添加额外文本框
把要加的文本框
<textarea id="real_comment" name="real_comment" class="comment-textarea"></textarea>
加入文件 comments.php 之后得到如下代码:
<?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="real_comment" name="real_comment" 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 所在的文件夹)新建一个单独的文件做跳板,如:wp-stop-spam.php,comment_form()
默认的action
是 wp-comments-post.php,现在要把action
改为 wp-stop-spam.php,只需将'action' => '/wp-stop-spam.php',
放到上面代码'class_submit' => 'submit'
的前一行即可。
跳板文件
接下来打开 wp-stop-spam.php,把下面代码放入并保存:
<?php nocache_headers(); $comment = trim($_POST['comment']); // Proceed with regular comments. if ( empty( $comment ) ) { $_POST['comment'] = trim($_POST['real_comment']); require( dirname(__FILE__) . '/wp-comments-post.php' ); } if ( ! empty( $comment ) ) { require( dirname(__FILE__) . '/wp-load.php' ); wp_die('You are not a human!'); }
大功告成,一旦 wp-stop-spam.php 收到提交上来的表单,首先检查comment
文本框是否为空,不为空就是机器填写的(comment
文本框做了隐藏后正常人是看不到的),直接组织评论生成并给出提示。
如果为空,则认为是正常访客提交的(正常访客只会在他们看到的real_comment
文本框内填写评论内容,接着将real_comment
文本框里的内容取作评论传给 wp-comments-post.php 生成评论。
禁止直接访问 wp-comments-post.php
如果还是不放心,那就直接禁止对 wp-comments-post.php 文件的直接访问,这个博客搭建在 nginx 上,把下面这段代码加入到 nginx 的主机配置文件重启 nginx 即可实现禁止直接访问 wp-comments-post.php 文件的目的(不影响 wp-stop-spam.php 文件 require 它)。
location = /wp-comments-post.php { return 404; }
用了两周效果很不错,没有一条垃圾评论!
以上方法对使用机器通过 wp-comment-post.php 提交的垃圾评论有效(对人工提交的垃圾评论爱莫能助),往往还有一些垃圾评论是通过 trackback 发送的,如需屏蔽 trackback 请参照如何屏蔽 trackback/pingback 垃圾评论
不怕机器,就怕人为的
@姜辰 人为的真没办法,手工垃圾评论只能指望 Akismet
@Shrek 我现在是关键词拉黑的模式
@姜辰 关键词局限性太大了。
@Shrek 关键词是他们的网址,如果他们无法提交网址,呢么所做的垃圾评论也是~~你懂得~
@姜辰 懂了
方法有点类似 https://leonax.net/p/6732/block-spam-comments-from-web-page/。不过,感觉其实加了 ajax 提交评论,然后禁止访问 wp-comments-post.php 文件,就能挡住绝大部分的垃圾评论了。
@老杨 他这个功能更高级
过两天参考参考你的,加到我的新主题上。
其实机器怎么都好防。人肉就难了。
@大致 这个方法只能防常规的垃圾评论,防不了 trackback 过来的垃圾评论,如果要试最好留着 akismet,另外又整了一个防 trackback 的方法,就等着今晚来 trackback 测试了。