当前位置: 首页 > 工具软件 > IP PHP Class > 使用案例 >

PHP判断ip是否在指定IP段内(微信支付回调IP段验证)

仲孙德惠
2023-12-01

需求:

项目中需要判断发起微信支付回调的IP在不在微信商户出口IP中,以防止私钥泄露别人发起伪装过的假回调造成损失

1获取客户端IP

/**
 * @explain 获取用户IP
 * @param int $type
 * @return mixed
 */
function get_client_ip($type = 0)
{
    $type = $type ? 1 : 0;
    static $ip = NULL;
    if ($ip !== NULL) return $ip[$type];
    if (isset($_SERVER['HTTP_X_REAL_IP'])) {//nginx 代理模式下,获取客户端真实IP
        $ip = $_SERVER['HTTP_X_REAL_IP'];
    } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {//客户端的ip
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (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['REMOTE_ADDR'])) {
        $ip = $_SERVER['REMOTE_ADDR'];//浏览当前页面的用户计算机的ip地址
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP地址合法验证
    $long = sprintf("%u", ip2long($ip));
    $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
}

2.验证IP是否在某个网段

/**
 * Notes: 判断IP在不在IP网段内
 * Date: 2019/6/18
 * Time: 15:22
 * @param $ip 要查询的IP地址
 * @param $network IP段  例: 192.168.1.1/24
 * @return bool
 */
function ip_in_network($ip, $network)
{
    $ip = (double) (sprintf("%u", ip2long($ip)));
    $s = explode('/', $network);
    $network_start = (double) (sprintf("%u", ip2long($s[0])));
    $network_len = pow(2, 32 - $s[1]);
    $network_end = $network_start + $network_len - 1;

    if ($ip >= $network_start && $ip <= $network_end) {
        return true;
    }
    return false;
}

3.判断

验证不通过则拒绝请求

class Notify extends Controller
{


    /**
     * 判断当前发起通知IP是否在微信商户出口IP段里,防止私钥泄露伪造通知
     * Notify constructor.
     * @param Request $request
     */
    public function __construct(Request $request)
    {
        $ip = get_client_ip();
        $whiteList = Setting::get('WX_NOTIFY_WHITE_LIST')->conf_value ?? '';
        $whiteList = explode(',',$whiteList);//ip白名单
        $verify = 0;
        foreach ($whiteList as $k => $v)
        {
            $verify = ip_in_network($ip,$v);
            if ($verify == 1)
                break;

        }
        $verify ==  0 && exit('Access Denied');
        
    }

 

 类似资料: