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以及恶意刷单

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:php 在电商类型的项目中,防止机器人伪造ip以及恶意刷单