一、cookie限制访问

为什么要提cookie限制访问呢?我可以只允许支持cookie的用户进行访问,大部分用户如果通过正常浏览器进行访问,基本都是支持cookie的,除非用户关闭了浏览器的cookie功能。我个人理解很多机器访问是不会像浏览器一样支持cookie的,从而达到限制异常访问的目的,不过该功能可能会对部分搜索引擎蜘蛛的抓取造成影响,所以我们需要提前进行甄别,我在前面的文章介绍过PHP如何识别蜘蛛,所以这里就不过多介绍了。同时访问者可以通过模拟真实用户传递cookie参数而对我们的判断进行欺骗,甚至他可能本身就是利用浏览器来进行访问的,比如部分采集工具就是调用浏览器来进行内容抓取的。显然该功能只能屏蔽部分异常访问,不过我们可以增加cookie的模拟难度来增加识别准确度。


function
checkcookie($str=null) {
   $return = false;
   if($str == 0 || $str == null) {
       $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
       $cookiename = '';
       $cookievalue = '';
       for ($i = 0; $i < 8; $i++) {
           $cookiename .= $characters[mt_rand(0, strlen($characters) - 1)];
       }
       for ($i = 0; $i < 16; $i++) {
           $cookievalue .= $characters[mt_rand(0, strlen($characters) - 1)];
       }
       setCookie($cookiename, $cookievalue, 5 ,'/', '', true, true);
   }
   if (isset($_COOKIE["$cookiename"]) && $cookievalue == $_COOKIE["$cookiename"]) {
       $return = true;
   }
   return $return;
}

该代码设置了一个随机的cookie 8位字符的键名和一个随机16位字符的对应值。我们再通过获取该cookie的值来对用户浏览器是否支持cookie进行判断。如果支持则checkcookie()返回true,否则返回false。虽然该方法并不是十分准确,但是也可以作为我们的一个判断依据。使用方法:


if
(checkcookie() == false) {
   die('您的浏览器不支持cookie');
}

二、$_SERVER['HTTP_ACCEPT']参数判断


if
(strpos($_SERVER['HTTP_ACCEPT'], 'text/html') !== false) {
   //可能是真实浏览器
}else{
   die('坚决杜绝一切非正常访问');
}

一般来说,如果浏览器不支持text/html,基本可以判断为非真实用户进行访问!

三、请求时间和频率判断

这里可以使用session来储存用户的访问时间,对两次访问的时间进行对比,如果间隔时间小于1秒,也可以进本判断为非正常访问。那么代码应该怎么写呢?


session_start()
; // 启动会话
//先判断用户是不是访问过,如果没有访问过, 设置会话变量
if (!isset($_SESSION['time'])) {
   $_SESSION['time'] = time();
} else {
   $usertime = time - $_SESSION['time'];//计算两次的访问时间差
   if ($usertime <= 1) {//如果时间差小于1秒,则退出脚本或者禁止访问
       die('禁止频繁访问');
   }
}

四、限制IP访问

如果我已知一些IP属于非正常访问,就像我上面截图中的访问行为,我百分百确定它是非正常访问!那么我可以通过判断IP进行访问限制:


$ips
= ['127.0.00.1', '192.168.1.1'];//限制访问的IP
foreach ($ips as $ip) {
   if ($ip == $_SERVER['REMOTE_ADDR']) {
       die('IP已被禁止访问');
   }
}

五、限制UA访问

根据一些模拟访问的UA头部信息特征进行限制,这里我们可以简单举个例子。下图中可以看出右侧的UA头部信息,然后分析它在网站上的操作,访问了一些不存在的页面,截图中看到返回的状态码是503,这是我根据IP和UA信息判断为非正常访问,特意反馈到浏览器的。


$ua
= $_SERVER['HTTP_USER_AGENT'];
//限制UA信息为空的访问
if ($ua == null) {
   die('访问异常,页面禁止加载')
}
//限制带有特定UA特征的访问
$array = ['Dalvik/2.1.0', 'Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1)'];
foreach ($array as $v) {
   if (strpos($ua, $v) > 0 || $ua == $v) {//判断用户的UA头部信息是否包含禁止的UA特征或者等于禁止的UA
       die('访问异常,页面禁止加载');
   }
}

六、结尾

以上介绍的都是一些禁止异常访问的思路,虽然不能准却识别异常访问,但是大部分简单的模拟访问、机器访问可以通过上面的这些方法进行识别并加以限制,以提高网站被暴力破解、异常请求所带来的一些安全威胁。如果你想要提供识别异常访问的准确度,你可以使用专业的第三方库来进行识别。本文中介绍的die()函数用于停止脚本继续执行,当然在禁止脚本运行之前,我们可以自定义一些状态码告诉浏览器我们想让它理解的一些信息。比如:


//
设置自定义状态码
http_response_code(403);
// 发送自定义头部信息
header('X-Custom-Status: Forbidden');
// 结束脚本执行
exit('对不起,您无权访问该资源。');


案例代码中发送了一个404状态,你也可以设置其他状态码,比如500,400,300等。