如何实现PHP限制单IP请求?完整方法与代码教程

在PHP中限制单IP请求频率是防止滥用和DDoS攻击的常见策略,以下是几种实现方法,根据需求选择适合的方案:

php限制单ip请求


方法1:基于Session计数(简单计数器)

<?php
session_start();
$ip = $_SERVER['REMOTE_ADDR'];
$limit = 10; // 允许的最大请求次数
$timeWindow = 60; // 时间窗口(秒)
// 初始化计数器
if (!isset($_SESSION['requests'])) {
    $_SESSION['requests'] = [
        'count' => 1,
        'start_time' => time()
    ];
} else {
    // 检查时间窗口
    if (time() - $_SESSION['requests']['start_time'] > $timeWindow) {
        // 重置计数器
        $_SESSION['requests'] = [
            'count' => 1,
            'start_time' => time()
        ];
    } else {
        // 增加计数
        $_SESSION['requests']['count']++;
        // 检查是否超过限制
        if ($_SESSION['requests']['count'] > $limit) {
            http_response_code(429); // Too Many Requests
            die("请求过于频繁,请稍后再试");
        }
    }
}
// 正常处理请求...
?>

缺点:Session基于Cookie,客户端禁用Cookie则失效。


方法2:使用文件存储(无Session依赖)

<?php
$ip = $_SERVER['REMOTE_ADDR'];
$limit = 10; // 最大请求次数
$timeWindow = 60; // 时间窗口(秒)
$logDir = __DIR__ . '/ip_logs/'; // 日志目录
// 确保目录存在
if (!is_dir($logDir)) mkdir($logDir, 0700, true);
$logFile = $logDir . md5($ip) . '.log';
// 读取现有记录
if (file_exists($logFile)) {
    $data = json_decode(file_get_contents($logFile), true);
    if (time() - $data['start_time'] > $timeWindow) {
        // 重置计数器
        $data = ['count' => 1, 'start_time' => time()];
    } else {
        $data['count']++;
        if ($data['count'] > $limit) {
            http_response_code(429);
            die("请求过多,请等待{$timeWindow}秒");
        }
    }
} else {
    $data = ['count' => 1, 'start_time' => time()];
}
// 保存记录
file_put_contents($logFile, json_encode($data));
?>

缺点:高并发时文件IO可能成为瓶颈。


方法3:使用Redis(高性能推荐)

<?php
$ip = $_SERVER['REMOTE_ADDR'];
$limit = 10; // 最大请求次数
$timeWindow = 60; // 时间窗口(秒)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379); // 连接Redis
$key = "rate_limit:$ip";
// 使用Redis计数器
$current = $redis->incr($key);
if ($current === 1) {
    // 首次设置时添加过期时间
    $redis->expire($key, $timeWindow);
} elseif ($current > $limit) {
    http_response_code(429);
    die("请求过于频繁");
}
// 正常处理请求...
?>

优势:高性能,适合分布式环境。

php限制单ip请求


方法4:.htaccess限制(Apache专用)

在项目根目录创建.htaccess文件:

<IfModule mod_rewrite.c>
    RewriteEngine on
    RewriteMap access counter:/path/to/access_map.txt
    RewriteCond ${access:%{REMOTE_ADDR}} >10
    RewriteRule ^ - [F,L]
</IfModule>

需配合脚本更新计数器,适用于熟悉Apache配置的场景。


关键注意事项:

  1. 获取真实IP:如果使用代理(如CDN),需通过HTTP_X_FORWARDED_FOR获取真实IP:
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];
  2. 分布式环境:使用Redis等共享存储,避免单点失效。
  3. 突发请求:考虑使用令牌桶算法(如Redis + Lua实现)。
  4. 白名单机制:对可信IP免除限制:
    $whitelist = ['192.168.1.1', '10.0.0.1'];
    if (in_array($ip, $whitelist)) return;

完整Redis令牌桶示例

<?php
$ip = $_SERVER['REMOTE_ADDR'];
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = "token_bucket:$ip";
$capacity = 20;    // 桶容量
$refillRate = 10;  // 每秒补充10个令牌
// 使用Lua脚本保证原子性
$lua = <<<LUA
local key = KEYS[1]
local now = tonumber(ARGV[1])
local capacity = tonumber(ARGV[2])
local refillRate = tonumber(ARGV[3])
local lastTime = tonumber(redis.call('hget', key, 'time') or now)
local tokens = tonumber(redis.call('hget', key, 'tokens') or capacity)
-- 计算补充的令牌
local refill = math.floor((now - lastTime) * refillRate)
tokens = math.min(capacity, tokens + refill)
-- 检查令牌是否足够
if tokens < 1 then
    return 0
end
-- 消耗令牌并更新
redis.call('hmset', key, 'tokens', tokens-1, 'time', now)
redis.call('expire', key, math.ceil(capacity/refillRate)*2)
return 1
LUA;
$result = $redis->eval($lua, [$key, time(), $capacity, $refillRate], 1);
if (!$result) {
    http_response_code(429);
    die("请求超出速率限制");
}
?>

根据业务需求选择方案,对于高并发场景,Redis方案是最佳选择,结合Lua脚本可保证原子性和精确控制。

php限制单ip请求

图片来源于AI模型,如侵权请联系管理员。作者:酷小编,如若转载,请注明出处:https://www.kufanyun.com/ask/290319.html

赞 (0)
上一篇 2026年2月10日 04:21
下一篇 2026年2月10日 04:26

相关推荐

  • 服务器多个IP作用是什么情况,多IP服务器有哪些用途?

    服务器配置多个IP,本质上是让一台服务器同时扮演多个独立网络身份,用来实现业务隔离、SEO优化、安全防护和合规访问等具体目标,这个结论听起来有点抽象,但放到实际场景里就很好理解:比如你做了一个站群,每个站点都想要独立IP,又不想买十几台物理服务器,那多IP方案就是最省钱的出路,服务器多个ip实际解决了哪些痛点业……

    2026年9月2日
    01232
  • 域名服务器和dns有什么区别?域名服务器与DNS服务器的区别及作用解析

    域名服务器和dns的区别可以一句话讲清:DNS是整套域名解析体系,域名服务器是这套体系里具体提供解析服务的那台机器,前者是规则和网络架构,后者是执行者,很多人把两者混为一谈,是因为日常配置网络时,大家习惯把“DNS服务器地址”简称为“DNS”,这才造成了认知上的重叠,域名服务器和dns到底有什么区别?要彻底分清……

    2026年9月9日
    01315
    • 服务器间歇性无响应是什么原因?如何排查解决?

      根源分析、排查逻辑与解决方案服务器间歇性无响应是IT运维中常见的复杂问题,指服务器在特定场景下(如高并发时段、特定操作触发时)出现短暂无响应、延迟或服务中断,而非持续性的宕机,这类问题对业务连续性、用户体验和系统稳定性构成直接威胁,需结合多维度因素深入排查与解决,常见原因分析:从硬件到软件的多维溯源服务器间歇性……

      2026年1月10日
      020
  • 熹妃传都是什么服务器,熹妃传有哪些区服选择

    官方经典区包括名门、世家、皇子、皇城等老区,合作区多为混服、专服和怀旧服,很多玩家第一次进游戏时,只看到一长串服务器列表,却搞不清这些名字背后到底有什么区别,有人因为选错服务器,玩到一半发现好友不在同一个大区,充值记录也对不上,其实只要看懂服务器的分类规则,选择起来并不复杂,熹妃传服务器究竟怎么分类熹妃传的服务……

    2026年10月22日
    0542
  • 服务器web发送流量什么意思,web发送流量是什么意思怎么理解?

    服务器web发送流量,简单说就是服务器作为网站服务端,在响应访客请求时向外发出的数据总量,包含网页HTML、图片、脚本、视频等响应内容;它属于出站流量,是带宽成本和异常排查的重点,你打开一个网页,浏览器向服务器要内容,服务器把网页“递”回来,这个“递出去”的过程就产生了web发送流量,很多站长盯着访问量看,却忽……

    2026年11月7日
    0335

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注