【问题标题】:PHP IP FilteringPHP IP 过滤
【发布时间】:2011-12-25 15:55:22
【问题描述】:

我希望允许用户根据他们的 IP 地址过滤他们的登录信息(我将在用户首选项中实施一项新设置)。

所以如果用户有特定ip登录且没有限制,则登录成功。

在任何其他情况下,我都在想这个

如果用户选择他的完整 IP,如 67.31.85.47 并且他有这个 IP,那么登录是好的 如果用户选择 67.31.85.* 并拥有此 IP,则登录良好 如果用户选择 67.31.. 并拥有此 IP,则登录良好 如果用户选择 67...* 并拥有此 IP,则登录良好 其他情况无效

用户最多可以选择 5 个 IP 限制。例如:

67.31.*.*
167.77.47.*
62.11.28.28
25.57.*.*
169.*.*.*

我正在尝试使用explode 剥离IP,然后与他设置的所有限制进行比较。 这可能会很慢,因为我必须检查 5 次 * 4(4 = IP 在点上爆炸)

有更快的方法吗? 谢谢

【问题讨论】:

  • 考虑将这些 IP 转换为普通整数并使用网络掩码。然后对要检查的每个 IP 地址进行简单的按位与运算。 if ((userIP && netmask) == (filterIP && netmask)) { ok to go }.
  • 由于您似乎是在老式 /8 边界上进行过滤,因此您需要 3 个网络掩码。 0xFF000000、0xFFFF0000、0xFFFFFF00。将相关掩码应用于表中的每个 ip,将其应用于用户的 IP,如果掩码值相等,则它们在同一个 IP 块中。

标签: php ip filtering


【解决方案1】:
$auth_ip=array();
$client_ip=array();
$client_ip=explode(".", $_SERVER['REMOTE_ADDR']);
$auth_ip=explode("\n", $patner_name_id[0]['client_ip']);
$j=0;
$flag=0;

foreach ($auth_ip as $value) {
    $i=0;
    $value=explode(".", $value);
    foreach ($value as $valueip) {
        if($valueip!="*") { 
            if($valueip!=$client_ip[$i]){
                $flag=1;
                 break;
            }
            $i++;
        }
        else {
            $i++;
            continue;
        }               
    }
}

if($flag==1){
    header("Location:".$default_company);           
    exit;
}

【讨论】:

    【解决方案2】:
    <?php
    function testIP($ip) {
        if($ip == '*' || $ip == '*.*.*.*') {
            return TRUE;
        }
        if($_SERVER['REMOTE_ADDR'] == $ip) {
            return TRUE;
        }
        $mask = str_replace('.*', '', $ip);
        return strpos($_SERVER['REMOTE_ADDR'], $mask) === 0;
    }
    
    $_SERVER['REMOTE_ADDR'] = '70.69.68.67';
    
    $ip = '1.11.1.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '2.34.9.1';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '70.11.*.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '70.69.68.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '70.69.*.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '70.*.*.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '*.*.*.*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    $ip = '*';
    echo "Is $ip good: "; var_dump(testIP($ip));
    

    将输出:

    Is 1.11.1.* good: bool(false)
    Is 2.34.9.1 good: bool(false)
    Is 70.11.*.* good: bool(false)
    Is 70.69.68.* good: bool(true)
    Is 70.69.*.* good: bool(true)
    Is 70.*.*.* good: bool(true)
    Is *.*.*.* good: bool(true)
    Is * good: bool(true)
    

    如果您正在寻找特定的 ip(无通配符)检查,您可以使用:

    function is_private_ip($ip) {
      return filter_var($ip, FILTER_VALIDATE_IP) != FALSE;
    }
    

    var_dump(is_private_ip('82.237.3.3')); var_dump(is_private_ip('748.1234.5.4'));

    【讨论】:

      【解决方案3】:

      也许这个想法对你有帮助:

      <?php
      $ip_restrict = "67.31.*.*
      167.77.47.*
      62.11.28.28
      25.57.*.*
      169.*.*.*";
      
      $ip_restrict = array_flip(explode("\n", $ip_restrict));
      $ip = preg_match("!([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)!", $_SERVER['REMOTE_ADDR'], $ip_match);
      
      
      $ip_in_blacklist = false;
      $ip_check_1 = $ip_match[1] . '.*.*.*';
      $ip_check_2 = $ip_match[1] . '.' . $ip_match[2] . '.*.*';
      $ip_check_3 = $ip_match[1] . '.' . $ip_match[2] . '.' . $ip_match[3] . '.*';
      $ip_check_4 = $ip_match[1] . '.' . $ip_match[2] . '.' . $ip_match[3] . '.' . $ip_match[4];
      
      if (isset($ip_restrict[$ip_check_1]) || isset($ip_restrict[$ip_check_2]) || isset($ip_restrict[$ip_check_3]) || isset($ip_restrict[$ip_check_4])) {
          $ip_in_blacklist = true;
      }
      
      var_dump($ip_in_blacklist);
      

      ;

      【讨论】:

      • 为什么要使用 preg_match?为什么不爆炸?有什么区别?
      • 很容易格式化和验证 :) 你可以使用explode,我看不出有什么区别
      • explode 不使用 regexp vs preg_match 是
      猜你喜欢
      • 1970-01-01
      • 2012-06-24
      • 1970-01-01
      • 2019-07-27
      • 2017-01-21
      • 2013-07-13
      • 2016-12-04
      • 2022-12-02
      • 2010-12-11
      相关资源
      最近更新 更多