个人网站的表单留言功能一般用于与访客交流,有多种成熟的垃圾评论管理方法可供选择,如reCaptcha、Akismet插件,甚至直接使用第三方评论交流工具。然而,对于一些企业网站,尤其是产品推广类网站来说,表单通常用于获取客户询价,是访客转化的重要工具,网站管理员在对待这些垃圾留言管理上通常非常谨慎。 不幸的是,很多提供留言功能的企业网站每天都接受大量的垃圾留言,一些企业的信息系统中,正常的信息甚至都被淹没在垃圾信息之中,大量的精力被浪费在处理这些信息上。
这逼得企业不得不采取措施,如增加验证码、使用关键词屏蔽、网址屏蔽功能、留言评级插件等。但这里会有几个问题,一是增加验证码会增加操作复杂度,很多企业不希望给客户制造难题,以免劝退他们;二是网站咨询本身都有限,担心一些关键词屏蔽或评级插件误伤正常留言,从而遗漏商机。
针对这一情况,我之前的做法是控制不让发重复信息,控制一条信息内链接的数量,同时增加灰名单功能。在灰名单内包含关键词的留言一律放到垃圾箱内,而留言中包含黑名单的内容则直接拒绝,这能屏蔽掉一些有特征的垃圾留言。
然而,仍然有不少漏网之鱼,他们要么是纯垃圾信息,要么是各种推销信息。每天研究他们提取屏蔽关键词也是一个浪费生命的工作。如何以低成本、一劳永逸的方式解决这些问题成为了不得不做的事情。
实际上经过分析,可以发现,这些垃圾留言都是通过爬虫发布的。一些不良爬虫在爬取网页之后,分析得出网站提供表单功能,然后自动往action地址发送数据。所以可以推测,大部分垃圾留言都不是通过浏览器发送的。那么是否可以通过User-agent白名单实现屏蔽呢?肯定不行,破坏者不会连User-agent伪装都不懂。
那么使用浏览器和不使用浏览器有什么区别呢?最主要的区别就是对页面信息的处理。试想一个访客来到一个包含表单的页面之后,浏览器会首先加载此页面的HTML代码,然后解析加载页面上的其他资源(图片、视频等等),最后渲染成可视画面。而爬虫通常则不会加载其他资源,只是分析页面的HTML代码。
基于这一点,我们可以做一些操作。当浏览器解析页面时,在某个请求中给浏览器写入一个cookie。浏览器请求其他资源(包括提交表单)时都会在请求中加上此cookie,而爬虫通常则不会。我们在表单处理程序中加入检测cookie的程序,就可以很好地对这些垃圾信息进行防护。
具体实现方法如下:
1. 在所有页面上增加一个Javascript,向后端服务器发送请求。如果使用CDN,必须保证此请求回源。如果有其他每次都要回源的请求,也可以公用。简单代码可以如下:
<script> new Image().src = '//example.com/getcaptcha.php'; </script>
2. 后端接受请求,并根据情况为客户端设置COOKIE。如果有需要,可以加密以便进行更复杂的校对。示例代码如下:
<?php header('Cache-Control: private, max-age=3600'); header('Content-Type: image/gif'); if (isset($_COOKIE['domai_captcha'])) setcookie('domai_captcha', time(), time() + 36000); echo base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'); ?>
3. 在表单处理程序中进行处置。示例代码如下:
<?php if (!isset($_COOKIE['domai_captcha'])) { header('HTTP/1.1 403 Forbidden'); die('禁止提交,非法访问'); } //下面是表单处理逻辑 ?>
当然,这只是逻辑实例代码。具体业务实现可能会更为复杂。
同时,大部分网站都使用CMS进行管理。改变源代码的方式并不优雅。较好的CMS如Domai CMS、WordPress都可以通过接口的方式实现。例如,Domai CMS可以在functions.php文件中进行以下编写:
<?php function _modify_feedback($request) { //不让没有获取COOKIE的爬虫直接提交表单,防止爬虫 if (!isset($_COOKIE['domai_captcha'])) { return new DM_Error(__('Message Not Sent', 'aishred'), __('Unauthorized Request, Please Use Your Browser to Access and Enable Javascript!', 'aishred')); } //下面还可以对数据进行扩展,处理前台有很多后端未定义的表单名的情况 } add_filter('pre_submit_feedback', '_modify_feedback'); ?>
有聪明的读者可能会想到,我一个访客都不想错过,如果有访客浏览器没有启用Javascript怎么办?很简单,可以使用noscript标签:
<noscript> <img width="1" height="1" src="//example.com/getcaptcha.php" alt=""> </noscript>
通过以上的操作,我们成功地减少了90%以上的垃圾留言。其他的通过后台IP屏蔽、手动管理等方式,工作量大大减少,访客无感,信息无遗漏。当然,上述代码只是逻辑实例代码,具体业务实现还需更为复杂的处理程序。
以上方式只是一种参考,无法屏蔽上述描述情况之外的攻击。一旦攻击者了解网站防护逻辑,可能导致灾难性后果,请综合考虑,本人不对任何后果负责。