垃圾评论和灌水机器人一直是各大论坛和博客最头疼的问题,为了解决该问题,我们需要先了解它的产生过程,然后有针对性地进行防御。
1. web浏览器的工作流程
用户在浏览器中输入网址,浏览器与服务器建立连接,发起HTTP请求,请求远程服务器中的URL,服务器接收请求,理解后进行响应,将响应结果返回给浏览器,浏览器解析收到的响应数据,最后呈现给用户。
其实,浏览器就是一个实现了HTTP协议的客户端软件。在浏览器与web服务器交互的过程中,浏览器始终扮演着一个忠实执行者的角色。据此可知,只要遵循HTTP协议和服务器进行交互,就实现了一个最简单的浏览器,只是这个浏览器只提供对数据的收发而不提供解析功能。而对于服务器端而言,无法判断是真正的浏览器还是一个虚拟的浏览器。
2. PHP中与HTTP协议相关的函数
如何发送HTTP请求呢?可以使用代码发送HTTP头,如服务器端的PHP、客户端的Ajax,也可以使用各种抓包工具构造HTTP Request包。
PHP中与HTTP协议相关的函数,主要有几下几种:
get_headers 函数:获取服务器响应一个HTTP请求时的所有标头。通常用此函数请求一个URL,根据其返回的数据判断状态码是否为200,就可以判定所请求的资源是否存在。
file 系列函数:包括fopen、file_get_contents等,可以用来操作文件,也可以请求一个网络上的资源。
stream_* 系列函数:发送请求,包括但不限于HTTP协议。
socket 系列函数:通过socket(套接字)发送和请求数据,包括但不限于HTTP协议。
cURL 扩展库:PHP的一个扩展,这是一个封装的函数库,可以用来模拟浏览器和服务器进行交互,功能比较强大。
header 函数:可用此函数发送原始的HTTP头,需要注意的是,此函数之前不能有任何输出包括空格等。
这里用最简单的方式,即使用 file 系列函数发送HTTP请求。
我们经常用 file_get_contents 函数获取文件的内容,实际上这个函数还可以打开一个网络地址,实现简单的网页抓取。用 file_get_contents 或者 fopen、file、readfile等函数读取URL时,会自动创建一个 $http_response_header 变量,该变量中保存了HTTP响应的报头。使用 fopen 等函数打开的数据流信息还可以用
stream_get_meta_data 获取。
一个简单的HTTP协议使用示例:
';
$fp = fopen('http://www.baidu.com', 'r');
var_dump(stream_get_meta_data($fp));
fclose($fp);
echo '
';
var_dump(get_headers('http://demo.com'));
?>
3. 模拟灌水机器人
上述 file 系列函数,在 PHP5 中新增了 context 参数,使得它们更加灵活,通过该参数可以定制 HTTP 请求,甚至POST数据。下面我们就利用 file_get_contents 函数发送请求,模拟一个灌水机器人向一个博客页面发送评论。
首先,打开某博客页面,查看评论表单所需的字段和表单的提交方式,假设所需字段只有一个 comment,表单采用的是 POST 方式提交。
然后,新建一个robot.php文件,用代码构建一个 HTTP 请求,代码如下:
'this is a robot comment');
$data = http_build_query($data);
$host = "Host: demo.com\r\n";
$content_type = "Content-type: application/x-www-form-urlencoded; charset=UTF-8\r\n";
$content_length = "Content-length: ".strlen($data)."\r\n";
$user_agent = "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:48.0) Gecko/20100101 Firefox/48.0"."\r\n";
$header = $host.$content_type.$content_length.$user_agent;
$options = array(
'http' => array(
'method' => 'POST',
'header' => $header,
'content' => $data
)
);
$context = stream_context_create($options);
$html = file_get_contents('http://demo.com/?id=1', false, $context);
echo $html;
?>
最后,运行 robot.php 文件即可。
如果是简单的页面抓取或数据提交,可以考虑使用 file_get_contents 函数,较为复杂的情况则需要使用cURL。但它们的本质都是一样的,都需要用到HTTP协议。
4. 使用抓包工具构造和提交HTTP请求
这里以 Fiddler 抓包软件为例。
打开 Fiddler,然后在浏览器中打开要进行评论的博客,输入评论后提交表单,用 Fiddler 工具,获取到提交评论时的原始请求数据,进行复制。然后,清空 Fiddler 左侧面板中的所有请求记录,点击 Fiddler 右侧面板的 Composer 按钮,再点击 Raw 按钮,将刚刚复制的原始请求数据粘贴到 Raw 下方的编辑框,可对原始请求数据进行更改,构造自己的 HTTP 请求。最后,点击最右侧的
Execute 按钮,就可以提交 HTTP 请求了。
5. 如何预防灌水机器人
预防灌水机器人的方法,主要有以下几种:
- IP限制。其原理在于IP难以伪造,即使是拨号用户,虽然IP可变,但有了IP限制后,就加大了灌水机器人的攻击难度。
- 验证码。用户提交评论时,要求其必须输入验证码方可提交,还可适当地加大验证码的识别难度。
- Token法。在表单中加一个隐藏的Token字段,Token的值可变,每次提交表单时,服务器都对Token的值进行校验。
- 审核机制。所有的评论都需要网站管理员审核后,方可显示,这在一方面加大了管理人员的工作量,但却在理论上可以完全阻止垃圾评论,这是最无奈也是最有效的方法。