由于简单的表单本身可以跨域远程提交,服务器端如果不对提交的表单进行真伪判断,那么相关博客或者网站都会受到各式各样的垃圾留言骚扰。如果网站不及时清理这些垃圾留言,那么整个网站的可读性将会变得越来越糟糕,最后完全被垃圾浏览给占领了。
WordPress非常受欢迎的一个官方的插件 Akismet,就是一个不错的垃圾留言阻击工具,它通过后台大数据分析来识别垃圾评论。
不过除了 Akismet,我还有安装另外一个插件,这个插件很小巧,并且我觉得思路很不错。通过这两个插件来可以过滤很多的垃圾评论。
作者的思路是这样的:
为什么人类应该通过填充验证码(CAPTCHA)证明他们是人类?应该是让机器人通过 JavaScript 来证明他们不是机器人!
下面说说这个插件 anti-spam 使用的算法。
这个算法是基于 2 个方法:不可见的 JS 验证码(invisible js-captcha)
和不可见的输入框陷阱(invisible input trap)
。
不可见的 JS 验证码 invisible js-captcha
不可见的 JS 验证码(invisible js-captcha)
方法基于一个事实:机器人在他们的在程序中不会执行 JavaScript 代码。
所以默认在输出 HTML 评论框的时候,加入了一个隐藏的问题和输入框,问题是今年是公元 xxxx 年。
如果用户访问网站,这个输入框答案会被 JavaScript 自动回答,并且会被 JavaScript 和css 的手段隐藏起来,不让用户看到。
如果机器人去填写答案没有填写正确,那么就会被判定是垃圾信息。
作者实现很鸡贼,其实这里有两个输入框,一个输入框是正确的答案,一个输入框是错误的答案。
<p class="antispam-group antispam-group-q" style="clear: both;"> <label>Current ye@r <span class="required">*</span></label> <input type="hidden" name="antspm-a" class="antispam-control antispam-control-a" value="'.date('Y').'" /> <input type="text" name="antspm-q" class="antispam-control antispam-control-q" value="'.ANTISPAM_PLUGIN_VERSION.'" autocomplete="off" /> </p>
JS 自动回答答案如果用户没有开启 JavaScirpt ,那么需要在这里情况内容,输入正确的答案。否者在后台就被判断是无效留言。
// 对表单答案添加答案,答案已经在 antispam-control-a 提供出来了。 elements = document.querySelectorAll('.antispam-control-q'); len = elements.length; for (i = 0; i < len; i++) { // set answer into other input instead of user elements[i].value = answer; } ... // 这里利用 JavaScript 添加一个动态的表单 // 如果没有开启 dynamic_control = document.createElement('input'); dynamic_control.setAttribute('type', 'hidden'); dynamic_control.setAttribute('name', 'antspm-d'); dynamic_control.setAttribute('class', 'antispam-control antispam-control-d'); dynamic_control.setAttribute('value', current_year); ... elements[i].appendChild(dynamic_control);
if ( $antspm_q != date('Y') ) { // year-answer is wrong - it is spam if ( $antspm_d != date('Y') ) { // extra js-only check: there is no js added input - it is spam $spam_flag = true; if (empty($antspm_q)) { // empty answer - it is spam $antispam_error_message .= 'Error: empty answer. ['.esc_attr( $antspm_q ).']<br> '.$rn; } else { $antispam_error_message .= 'Error: answer is wrong. ['.esc_attr( $antspm_q ).']<br> '.$rn; } } }
如果用户没有启用 JavaScript 会怎么样呢?后台判断逻辑片段
用户会在提交表单中看到今天是公元多少年的问题,然后需要将错误的答案修改成正确的答案。这样在上面的后台检测脚本中就会发现,这里填写是正确的。就不用再关心 JavaScript 动态的答案了。
不可见的输入框陷阱 invisible input trap
不可见的输入框陷阱(invisible input trap)
是基于一个事实:大多数机器人遇到 email
或者 url
关键字表单会自动填充一些信息。
因此在评论框中增加一个隐藏字段,正常用户是看不到这个字段,所以也不会去填写它。
// 默认不展示给用户看。 <p class="antispam-group antispam-group-e" style="display: none;"> <label>Leave this field empty</label> <input type="text" name="antspm-e-email-url-website" class="antispam-control antispam-control-e" value="" autocomplete="off" /> </p>
后台的判断逻辑片段但是机器人是可以看到这个字段的,如果在这里填写了任何东西,那么就会被判定为机器人。
// 如果填写了这个表单,那么就被判定是垃圾信息了 if ( ! empty($antspm_e)) { // trap field is not empty - it is spam $spam_flag = true; $antispam_error_message .= 'Error: field should be empty. ['.esc_attr( $antspm_e ).']<br> '.$rn; }
从后台效果来看,这个插件的效果很好,很少遇到垃圾留言。总结一下目前的一些垃圾机器人无法执行 JavaScript,所以很多利用这个特性就可以做一些排除了。很多的第三方评论都是利用 JS 展示出来了。不过很优秀的 Disqus 在国内经常不可用。
总结一下防范表单机器人的通用方法:
方法一: 使用访客行为分析程序而不是验证码来判断是否机器人
有一些插件,比如在Wordpress上经常使用的Akismet,可以通过IP频率、Cookies等信息判断机器人。AKismet不仅仅用于wordpess,还可以安装在企业网站甚至电商网站上。
道高一尺魔高一丈,已经有针对Akismet的机器人出现了,但这么做起码可以避开大多数机器人,并且远离坑爹的验证码。
方法二:使用诱饵表单项
这个技术很简单,就是在你的表单里面,放一个单行文本框,文本框内写着:如果你不是机器人,请删掉这行数据。
机器人来了,肯定不管三七二一直接提交。那么我们在后台判断,凡是填写了表单的访问都是机器人,凡是删除这行数据的人都是访客。
这个方法的优点在于,不需要用户填写验证码了。缺点在于,用户还是需要手动删除一行数据,但这总算相对轻松很多吧。
诱饵技术还有一个变种,就是用隐含文本框,里面什么内容都不填写。一些初级的机器人,只要见到表单都会照例填写一些东东进去,而用户看不到表单自然也不会填写。这个方法比上面的更简单,但只能防住比较笨的机器人。如果我们稍作改造,就可以防住不少聪明机器人,比如我们的诱饵表单不是固定的,而是随机生成的,那么机器人的难度会高很多。
方法三:将验证码和用户正常数据结合在一起
比如用户信息中,有一个必填项是性别。当用户填写性别的时候,跳出两个选项:
我是帅哥(传递一个隐含变量 100981)
我是美女(传递一个隐含变量 283397)
第二次访问的时候,跳出两个选项
我是帅哥(传递一个隐含变量 997301)
我是美女(传递一个隐含变量 000981)
你可以随机生成几十组这样变量对应表,每60分钟该表格自动更新一次数据。首先机器人无法判断每次需要正确传递的变量。如果某个不怀好意的垃圾制造者用遍历法分析了你的代码找到了对应关系,然后做出新的机器人,他也不可能每小时来遍历一次。
这个方法的好处在于,用户丝毫感觉不出来这是一个验证码,而机器人则束手无策,即使有垃圾制造者人工参与,破解的难度也很大。这个方法是否十全十美呢?非也。如果某个垃圾制造者专门针对你的网站做个机器人,先获取表单数据,然后再Post数据,就顺利过关了。为了防止这种情况,我们可以用java或者ajax技术来展现选项,对方改造机器人的成本也会增加很多。
世界上没有十全十美无懈可击的解决方法,但对所有关注用户体验的站长或者网站推广人员,亿推海外推广都给予一个忠告:别小看验证码,别将防范垃圾信息的问题转嫁到用户身上,验证码有的时候不仅没有帮你解决问题,反而带来更多的问题,而这一切都几乎不被站长察觉。摆脱验证码系统,能够改善用户体验,并直接提升转化率。