在PHP中限制IP访问可以通过多种方式实现,以下提供三种常见方法,根据需求选择适合的方案:

方法1:直接通过PHP代码限制(适合简单场景)
<?php
// 允许访问的IP列表(支持单个IP或CIDR网段)
$allowed_ips = [
'192.168.1.100', // 单个IP
'203.0.113.0/24', // CIDR网段
'::1', // IPv6本地地址
];
// 获取客户端真实IP(考虑代理情况)
function get_client_ip() {
$ip_keys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'REMOTE_ADDR'];
foreach ($ip_keys as $key) {
if (!empty($_SERVER[$key])) {
$ips = explode(',', $_SERVER[$key]);
$ip = trim(end($ips));
if (filter_var($ip, FILTER_VALIDATE_IP)) {
return $ip;
}
}
}
return '0.0.0.0'; // 默认值
}
$client_ip = get_client_ip();
// CIDR匹配函数
function ip_in_cidr($ip, $cidr) {
if (strpos($cidr, '/') === false) {
return $ip === $cidr; // 直接比较IP
}
list($subnet, $mask) = explode('/', $cidr);
$ip_bin = inet_pton($ip);
$subnet_bin = inet_pton($subnet);
$mask_bin = str_repeat('f', $mask >> 2);
switch ($mask & 3) {
case 3: $mask_bin .= 'e'; break;
case 2: $mask_bin .= 'c'; break;
case 1: $mask_bin .= '8'; break;
}
$mask_bin = pack('H*', str_pad($mask_bin, 32, '0'));
return ($ip_bin & $mask_bin) === $subnet_bin;
}
// 检查IP是否允许访问
$allowed = false;
foreach ($allowed_ips as $allowed_ip) {
if (ip_in_cidr($client_ip, $allowed_ip)) {
$allowed = true;
break;
}
}
if (!$allowed) {
http_response_code(403); // 禁止访问
exit("您的IP ($client_ip) 无访问权限");
}
// 允许访问的代码继续执行...
echo "欢迎访问!";
?>
方法2:通过.htaccess限制(Apache服务器)
在网站根目录创建.htaccess文件:
# 允许特定IP
<RequireAll>
Require ip 192.168.1.100
Require ip 203.0.113.0/24
Require ip ::1
</RequireAll>
# 或禁止特定IP(二选一)
# Deny from 192.168.1.50
# Deny from 203.0.113.55
方法3:通过防火墙限制(服务器级)
Linux iptables示例:
# 允许特定IP访问80端口 sudo iptables -A INPUT -p tcp --dport 80 -s 192.168.1.100 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 80 -s 203.0.113.0/24 -j ACCEPT # 拒绝其他所有IP访问80端口 sudo iptables -A INPUT -p tcp --dport 80 -j DROP
关键注意事项:
-
IP获取可靠性
REMOTE_ADDR是直连IP(最可靠)- 代理场景需检查
X-Forwarded-For,但需警惕伪造风险 - 使用
filter_var($ip, FILTER_VALIDATE_IP)验证IP格式
-
IPv6支持
- 示例代码已兼容IPv6地址(如
:1)
- 示例代码已兼容IPv6地址(如
-
性能优化

- 频繁检查时建议缓存IP列表
- 大量IP规则建议使用数据库或缓存系统
-
动态IP处理
- 动态IP用户可结合白名单+密码验证
- 或使用IP段放宽限制(如
/24网段)
-
错误处理
- 被拒绝时返回
403 Forbidden状态码 - 可记录日志便于审计:
file_put_contents('blocked.log', "$client_ipn", FILE_APPEND);
- 被拒绝时返回
扩展场景:国家/地区级限制
使用第三方库(如 geoip2/geoip2):
require 'vendor/autoload.php';
use GeoIp2DatabaseReader;
$reader = new Reader('/path/to/GeoLite2-Country.mmdb');
$record = $reader->country(get_client_ip());
if ($record->country->isoCode !== 'CN') { // 仅允许中国IP
http_response_code(403);
exit("您所在地区禁止访问");
}
提示:地理数据库需定期更新,可从 MaxMind 下载。
根据实际需求选择方案,简单需求用PHP代码或.htaccess,高性能要求建议使用服务器防火墙。
图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/291532.html

