一个用于请求频率限制和IP过滤的PHP中间件包。
- IP 白名单和黑名单(支持 IPv4/IPv6 网段)
- 请求频率限制(基于 Redis)
- 自动黑名单机制(可配置启用/禁用)
- Redis 异常容错处理
- 可配置的策略执行模式(阻止/非阻止)
- 全面的策略节点日志记录
- 中间件集成
- 可自定义的日志处理器(支持 PSR-3 标准)
- 请求数最大值跟踪记录到文件或Redis
当前版本: 1.1.0
查看 CHANGELOG.md 了解详细的版本历史。
使用Composer安装:
composer require php-rate-limit-middleware/php-rate-limit-middleware如果要使用限流功能,需要安装 Redis 扩展:
- 下载适合您PHP版本的 php_redis.dll
- 将其放置在 PHP 扩展目录中
- 在 php.ini 中添加:
extension=php_redis.dll - 重启 Web 服务器
pecl install redis然后在 php.ini 中添加: extension=redis
如果不方便安装 PHP 扩展,可以使用 Composer 包作为替代:
composer require phpredis/phpredis<?php
use QnvipCom\PhpRateLimitMiddleware\Config\Config;
use QnvipCom\PhpRateLimitMiddleware\RateLimit\RateLimiter;
use QnvipCom\PhpRateLimitMiddleware\Middleware\FilterMiddleware;
// 加载配置
$config = Config::load();
// 初始化Redis连接
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 创建速率限制器实例(可选地指定键前缀)
$rateLimiter = new RateLimiter($redis, $config['rate_limit'], 'myapp_rate_limit');
// 创建中间件实例
$middleware = new FilterMiddleware($config, $rateLimiter);
// 在您的应用中使用中间件处理请求
$response = $middleware->handle($request, function($req) {
// 处理实际业务逻辑
return $next($req);
});
// 手动管理自动黑名单
if ($rateLimiter->isIpAutoBlacklisted('192.168.1.100')) {
echo "IP 192.168.1.100 在自动黑名单中";
}
// 手动将IP从自动黑名单中移除
$rateLimiter->removeFromAutoBlacklist('192.168.1.100');
// 获取所有自动黑名单中的IP
$blacklistedIps = $rateLimiter->getAutoBlacklist();<?php
use QnvipCom\PhpRateLimitMiddleware\Config\Config;
use QnvipCom\PhpRateLimitMiddleware\RateLimit\RateLimiter;
use QnvipCom\PhpRateLimitMiddleware\Middleware\FilterMiddleware;
use QnvipCom\PhpRateLimitMiddleware\Logger\LoggerInterface;
// 创建一个适配 Laravel 日志系统的日志处理器
class LaravelLogger implements LoggerInterface
{
private $logger;
public function __construct(\Illuminate\Log\LogManager $logger)
{
$this->logger = $logger;
}
public function emergency(string $message, array $context = []): void
{
$this->logger->emergency($message, $context);
}
public function alert(string $message, array $context = []): void
{
$this->logger->alert($message, $context);
}
public function critical(string $message, array $context = []): void
{
$this->logger->critical($message, $context);
}
public function error(string $message, array $context = []): void
{
$this->logger->error($message, $context);
}
public function warning(string $message, array $context = []): void
{
$this->logger->warning($message, $context);
}
public function notice(string $message, array $context = []): void
{
$this->logger->notice($message, $context);
}
public function info(string $message, array $context = []): void
{
$this->logger->info($message, $context);
}
public function debug(string $message, array $context = []): void
{
$this->logger->debug($message, $context);
}
public function log($level, string $message, array $context = []): void
{
$this->logger->log($level, $message, $context);
}
}
// 加载配置
$config = Config::load();
// 初始化Redis连接
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 创建自定义日志处理器
$logger = new LaravelLogger(app('log'));
// 创建速率限制器实例(可选地指定键前缀)
$rateLimiter = new RateLimiter($redis, $config['rate_limit'], 'myapp_rate_limit', $logger);
// 创建中间件实例
$middleware = new FilterMiddleware($config, $rateLimiter, $logger);<?php
use QnvipCom\PhpRateLimitMiddleware\Config\Config;
use QnvipCom\PhpRateLimitMiddleware\RateLimit\RateLimiter;
use QnvipCom\PhpRateLimitMiddleware\Middleware\FilterMiddleware;
use QnvipCom\PhpRateLimitMiddleware\Logger\LoggerInterface;
// 创建一个适配 ThinkPHP5 日志系统的日志处理器
class ThinkPHPLogger implements LoggerInterface
{
public function emergency(string $message, array $context = []): void
{
\think\facade\Log::emergency($message, $context);
}
public function alert(string $message, array $context = []): void
{
\think\facade\Log::alert($message, $context);
}
public function critical(string $message, array $context = []): void
{
\think\facade\Log::critical($message, $context);
}
public function error(string $message, array $context = []): void
{
\think\facade\Log::error($message, $context);
}
public function warning(string $message, array $context = []): void
{
\think\facade\Log::warning($message, $context);
}
public function notice(string $message, array $context = []): void
{
\think\facade\Log::notice($message, $context);
}
public function info(string $message, array $context = []): void
{
\think\facade\Log::info($message, $context);
}
public function debug(string $message, array $context = []): void
{
\think\facade\Log::debug($message, $context);
}
public function log($level, string $message, array $context = []): void
{
\think\facade\Log::record($message, $level, $context);
}
}
// 加载配置
$config = Config::load();
// 初始化Redis连接
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 创建自定义日志处理器
$logger = new ThinkPHPLogger();
// 创建速率限制器实例(可选地指定键前缀)
$rateLimiter = new RateLimiter($redis, $config['rate_limit'], 'myapp_rate_limit', $logger);
// 创建中间件实例
$middleware = new FilterMiddleware($config, $rateLimiter, $logger);默认配置包含以下选项:
ip_whitelist: IP白名单列表(支持精确IP地址和CIDR网段格式,如:192.168.0.0/16,也支持IPv6)ip_blacklist: IP黑名单列表(支持精确IP地址和CIDR网段格式,如:172.16.0.0/12,也支持IPv6)rate_limit.limit: 时间窗口内最大请求数rate_limit.duration: 时间窗口长度(秒)auto_blacklist.threshold: 自动加入黑名单的请求阈值(每时间窗口内的请求数)auto_blacklist.duration: 自动黑名单持续时间(秒)
您可以根据需要修改这些配置值。
'auto_blacklist' => [
'enabled' => true, // 是否启用自动黑名单功能
'threshold' => 100, // 触发自动黑名单的阈值(每分钟请求数)
'duration' => 3600, // 自动黑名单持续时间(秒),默认1小时,设为0或负数表示永久
]当某个 IP 在单位时间内的请求次数超过阈值时,会自动加入黑名单并在指定时间后自动解除。
若将 duration 设置为 0 或负数,则该 IP 会被永久列入黑名单,除非手动移除。
'middleware' => [
'block_on_violation' => true, // 是否在违反策略时阻止访问
'log_policy_violations' => true, // 是否记录策略违规日志
]默认情况下,当检测到违反策略的行为时(如IP在黑名单中、触发限流、在自动黑名单中),系统会阻止访问并返回相应的错误码。
当设置为 false 时,系统只会记录违规行为但允许访问继续进行,这在某些测试或监控场景中非常有用。
'rate_limit' => [
'limit' => 60, // 最大请求次数
'duration' => 60, // 时间窗口(秒)
'log_detailed' => true, // 是否记录详细日志
]当 log_detailed 设置为 true 时,限流器会记录更详细的日志信息,包括请求计数、限制值等。
'request_count_tracking' => [
'enabled' => false, // 是否启用请求数跟踪
'storage' => 'file', // 存储方式: 'file' 或 'redis'
'max_count_file' => '', // 存储最大请求数的文件路径 (当storage为'file'时使用)
'max_count_redis_key' => '' // 存储最大请求数的Redis键 (当storage为'redis'时使用)
]当启用请求数跟踪功能时,系统会将每个时间窗口内的最大请求数记录到指定的存储中(文件或Redis)。 这有助于监控系统负载和峰值流量。
系统会在以下关键节点记录日志:
- 请求开始处理时记录客户端IP
- IP白名单检查结果
- IP黑名单检查结果
- 自动黑名单检查结果
- 请求频率限制检查结果
- 最终处理结果(允许/拒绝)
默认情况下,日志通过 PHP 的 error_log 函数记录,可以通过配置 PHP 的 error_log 指令将日志输出到指定文件。
如果提供了自定义的日志处理器,则会使用该处理器记录日志。
当 Redis 出现连接异常或其他错误时,系统会记录错误日志但不会中断正常业务流程:
- IP 白名单/黑名单检查不受影响
- 请求频率限制会暂时跳过,允许请求通过
- 自动黑名单检查会暂时跳过,允许请求通过
- 所有 Redis 操作都有异常捕获,确保服务持续可用
要运行测试,需要先安装开发依赖:
composer install然后可以通过以下方式运行测试:
./vendor/bin/phpunitcomposer testtest.bat./test.sh./vendor/bin/phpunit tests/RateLimit/RateLimiterTest.php
./vendor/bin/phpunit tests/Middleware/FilterMiddlewareTest.php
./vendor/bin/phpunit tests/Middleware/IpMatchingTest.php
./vendor/bin/phpunit tests/Middleware/AutoBlacklistTest.php注意:测试需要 Redis 服务器运行在本地默认端口(6379)上。
要发布新版本,请更新以下文件:
- composer.json 中的版本号
- CHANGELOG.md 中的变更记录
- 使用 Git tag 标记新版本
本项目采用 MIT 许可证授权。