IP白名单的实现(PHP)

时间:2020-11-28 17:31:30

有些项目可能会用到一个IP地址的白名单黑名单之类的验证。

比如,只有IP地址在白名单中,才可以访问该系统。

那么此时,白名单的维护,一般是一个文件,里边是一些IP地址(每行一个IP),当然也有的可能是用数据库记录白名单。

当然,即使放在数据库中记录(方便管理),也可以在后台根据数据库生成IP白名单的配置文件,每次更新白名单时,都根据数据库数据,重新写一下白名单的配置文件。

这里,假设白名单的IP地址是存储在一个文件中:while_ips.conf

一般常见的两种情况:一种是白名单文件中的所有IP都是完整的,另一种是有的IP是有范围的(带.*)

一、每一个IP都是完整的IP

 127.0.0.0
192.168.1.1
192.168.1.2
192.168.1.30
123.200.20.200
123.101.21.201

  以上假设就是IP白名单。

此时的思路是,从文件中读取所有IP地址写入一个数组,每行就是一个元素。

然后判断当前IP是否在这个数组中。这样就实现了这个IP是不是在白名单的验证。

这种实现,比较简单。

 function white_ips($file)
{
$a = [];
if (is_file($file)) {// 判断是不是文件
$f = fopen($file, 'r');// 只读的方式打开文件
while (!feof($f)) {// 判断你是否在文件尾,不是文件尾则循环
$s = fgets($f);// 每次读出一行
$s = preg_replace('/\s*/', '', $s);// 先过滤掉多余的空格和空白
if (substr($s, 0, 1) != '#' && $s != '') {// 如果不是注释行,或者空行
$a[] = $s;// 记录有效数据
}
}
fclose($f);
}
return $a;
}

  $file是IP白名单文件的存储位置和文件名,其中会过滤掉注释的IP,同时也会过滤掉多余的空白和换行。避免意外出错。

 $arr = getWhiteIps('white_ips.conf');
$ip = '192.168.1.1';
$allow = 0;
if (in_array($ip, $arr)) {
$allow = 1;
}
echo $allow;

  通过这样调用和判断,就可以知道当前的IP是否在白名单了。

二、第二种情况是白名单配置文件中是有范围的

 127.*.*.*
10.*.*.*
192.168.*. *
192.168.1.1
123.200.20.200
123.101.21.201
210.10.22.*
210.123.135.*
#30.11.22.33
#119.123.2.15

  以上是假设IP白名单的文件内容

  此时的思路是,从文件中读取所有IP地址写入一个数组,每行就是一个元素。

  然后通过循环的方式,将当前IP和数组中的每一条数据进行比较(匹配),如果匹配上则白名单,否则不是。

  此时因为有范围,所以不能使用in_array这种简单的判断了。需要使用正则来判断。

  读取白名单配置文件的代码不变,改变判断方法即可。

 function checkIp($ip, $rule)
{
$rule_regexp = str_replace('.*', 'a', $rule);//将.*临时替换成别的符号(.和*都是正则中有特殊含义的符号)
$rule_regexp = preg_quote($rule_regexp, '/');//向规则字符串中增加转义,避免字符串中有其他特殊字符影响正则匹配,非必要语句本例可以忽略
$rule_regexp = str_replace('a','\.\d{1,3}', $rule_regexp);//将临时符号替换成正则表达式
if(preg_match('/^' . $rule_regexp . '$/', $ip)){
return 1;//匹配
}else{
return 0;//不匹配
}
} $arr = getWhiteIps('white_ips.conf');
$ip = '192.168.1.';
$allow = 0;
foreach ($arr as $rule) {
if(checkIp($ip, $rule)){
$allow = 1;//找到一个排配则标记白名单,然后结束循环
break;
}
}
echo $allow;

  这种有范围的验证,稍微复杂一点,需要逐一比对判断。利用正则匹配IP后,结束循环。