机器人伪造ip以及恶意刷单"/>
php 在电商类型的项目中,防止机器人伪造ip以及恶意刷单
最近这几天,总是被人捣乱恶意刷单,查ip发现都是无效ip,于是查找了资料后,再根据个人的想法提出可行的解决方案。
首先是获取ip的方法:
/*** 获取客户端IP地址* <br />来源:ThinkPHP* <br />"X-FORWARDED-FOR" 是代理服务器通过 HTTP Headers 提供的客户端IP。代理服务器可以伪造任何IP。* <br />要防止伪造,不要读这个IP即可(同时告诉用户不要用HTTP 代理)。* @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字* @param boolean $adv 是否进行高级模式获取(有可能被伪装) * @return mixed*/ function get_client_ip($type = 0, $adv = false) {$type = $type ? 1 : 0;static $ip = NULL;if ($ip !== NULL)return $ip[$type];if ($adv) {if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);$pos = array_search('unknown', $arr);if (false !== $pos)unset($arr[$pos]);$ip = trim($arr[0]);}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {$ip = $_SERVER['HTTP_CLIENT_IP'];} elseif (isset($_SERVER['REMOTE_ADDR'])) {$ip = $_SERVER['REMOTE_ADDR'];}} elseif (isset($_SERVER['REMOTE_ADDR'])) {$ip = $_SERVER['REMOTE_ADDR'];}// IP地址合法验证, 防止通过IP注入攻击$long = sprintf("%u", ip2long($ip));$ip = $long ? array($ip, $long) : array('0.0.0.0', 0);return $ip[$type]; }/*** 获得用户的真实IP地址* <br />来源:ecshop* <br />$_SERVER和getenv的区别,getenv不支持IIS的isapi方式运行的php* @access public* @return string*/ function real_ip() {static $realip = NULL;if ($realip !== NULL) {return $realip;}if (isset($_SERVER)) {if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);/* 取X-Forwarded-For中第一个非unknown的有效IP字符串 */foreach ($arr AS $ip) {$ip = trim($ip);if ($ip != 'unknown') {$realip = $ip;break;}}} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {$realip = $_SERVER['HTTP_CLIENT_IP'];} else {if (isset($_SERVER['REMOTE_ADDR'])) {$realip = $_SERVER['REMOTE_ADDR'];} else {$realip = '0.0.0.0';}}} else {if (getenv('HTTP_X_FORWARDED_FOR')) {$realip = getenv('HTTP_X_FORWARDED_FOR');} elseif (getenv('HTTP_CLIENT_IP')) {$realip = getenv('HTTP_CLIENT_IP');} else {$realip = getenv('REMOTE_ADDR');}}// 使用正则验证IP地址的有效性,防止伪造IP地址进行SQL注入攻击preg_match("/[\d\.]{7,15}/", $realip, $onlineip);$realip = !empty($onlineip[0]) ? $onlineip[0] : '0.0.0.0';return $realip; }
与thinkphp5内置的ip()方法相比使用real_ip()方法可以有效避免恶意的无效ip。
接着针对恶意刷单,当时一天经常被刷十几万单,完全避免是不可能的,只能说是减少这个ip的下单次数 并把这个ip加入到黑名单里。
* 思路 1.获取当前时间和当前时间前一分钟的时间戳 以及 2.当前时间和当前时间前一天时间戳 * 对于1=> 如果在这个时间范围内的当前ip下单超过5单 将这个ip加入黑名单 * 对与2=> 如果在24小时内的当前ip下单超过20单 将这个ip加入黑名单
$ip=$request->real_ip();
//当前时间 $nowTime = time();
//当前时间的前1分钟 $twoTime = time() - 60;
//当前时间的前24小时 $dayTime = time() - 3600*24; $condition = [ 'ip' => $ip, 'create_time' =>array('between',array($twoTime,$nowTime)), ]; $dayCondition = [ 'ip' => $ip, 'create_time' =>array('between',array($dayTime,$nowTime)), ]; //当前时间 一分钟半的时间内 刷单超过5单的,自动加入黑名单 $ipBad = Db('GoodsOrder')->field('ip,count(*) as count')->where($condition)->find(); //在第二天零点之前 刷单超过20单的,自动加入黑名单 $dayIpBad = Db('GoodsOrder')->field('ip,count(*) as count')->where($dayCondition)->find(); if($ipBad['count'] > 4 || $dayIpBad['count'] > 20){ $not_ip = Db::name('config')->where(array('uid'=>1))->field('ip_list')->find(); $not_ip = $not_ip['ip_list']; $not_ip = $not_ip.';'.$ip;
//将黑名单ip更新到后台
Db::name('config')->where(array('uid'=>1))->update(['ip_list'=>$not_ip]); return false; }
然后让前台的控制器继承一个Base控制器,在这个控制器当中去判断当前用户的ip地址是否在黑名单里,在的话强制跳转到404页面
namespace app\index\controller; use think\Controller; use think\Request; use think\Db; class Base extends Controller{ public function _initialize(){ $request = Request::instance();
//获取当前域名 $domain = $request->domain(); $ipAddress = $request->ip();
// uid 权限 uid=1代表总后台 $uid = 1; $badIp = $web_config = Db::name('config')->field('ip_list')->where(array('uid' => $uid))->find(); $badIp = explode(';',$badIp['ip_list']); $isin = in_array($ipAddress, $badIp); if($isin){ $url = $domain . '/' . 'index/error/error404'; header("Location: $url"); exit; } } }
更多推荐
php 在电商类型的项目中,防止机器人伪造ip以及恶意刷单
发布评论