语法种子 / iplimiter
一个PHP IP日志库(框架无关),用于跟踪通过IP地址的事件尝试次数以及上次尝试的时间。通过运行事件和规则集来决定通过/失败。支持禁止。
Requires
- php: ^7.3|^8.0
Requires (Dev)
- phpunit/phpunit: ^9.5
README
一个轻量级、框架无关的PHP IP地址日志库,用于跟踪各种类别事件的尝试次数和最后尝试的时间。事件是一个IP地址和类别字符串的组合。该库包括设置/获取禁止状态、删除单个事件或特定IP的所有事件等的辅助函数。
常见用途包括为应用程序中任何尝试的操作创建陷阱或代码级别的门/限制。
IPLimiter构造函数必须传递一个已连接的PDO对象以创建数据库表并记录事件。
库的核心功能是执行一组“规则”,然后IPLimiter将确定IP地址是否通过规则集,从而确定是否允许其继续。规则可以指定最大尝试次数、下次尝试之前必须经过的时间,以及是否将禁止状态考虑在内。以下是一个示例。
许可证:MIT。
作者:Sherri Wheeler。
当前版本:2.0.3。
特性
- 符合IPv4和IPv6地址。
- 简单易学易用。
- 跟踪并运行规则。
- 尝试次数。
- 上次尝试以来时间。
- 禁用状态。
- 在给定时间过后重置尝试次数。
- 灵活。IP地址和事件字符串可以是任何内容。
- 使用PHPUnit进行单元测试。
- 兼容PHP 7.3+、8.0+、8.1+。
安装
使用Composer安装。
composer require syntaxseed/iplimiter ^2.0
主版本2与版本1不兼容。
使用 - 快速开始
首先确保您有一个连接的PDO对象。(https://php.ac.cn/manual/en/book.pdo.php)。或者实现一个新的类,该类实现所包含的DatabaseInterface。包含了一个PDO连接的类实现(DatabasePDO)。
将命名空间导入到您的应用程序中
use Syntaxseed\IPLimiter\IPLimiter; use Syntaxseed\IPLimiter\DatabasePDO;
初始化一个PDO对象,并使用它创建一个新的IPLimiter实例。第二个参数是IPLimiter要使用的数据库表名。包含了一个实现DatabaseInterface的DatabasePDO类。
$ipLimiter = new IPLimiter(new DatabasePDO($pdo), 'syntaxseed_iplimiter');
如果您不使用PDO,您可以实现一个DB包装类,该类实现了'Syntaxseed\IPLimiter\DatabaseInterface。
如果不存在,则创建IPLimiter表
此和未来的函数将使用构造函数注入的DatabaseInterface对象。
$result = $ipLimiter->migrate();
只运行一次。这将为您创建初始表。
记录一个新事件。
事件有一个IP地址和一个字符串'category'。处理事件需要设置事件。
$ipLimiter->event('123.123.0.1', 'sendmail'); $ipLimiter->log();
或者,您可以通过方法链初始化对象、设置事件和记录
$ipLimiter = (new IPLimiter(new DatabasePDO($pdo), 'syntaxseed_iplimiter')) ->event('123.123.0.1', 'sendmail') ->log();
获取数据库中是否存在事件。
$ipLimiter->event('111.111.111.111', 'sendmail'); $isLogged = $ipLimiter->exists(); // $isLogged is false. $ipLimiter->log(); $isLogged = $ipLimiter->exists(); // $isLogged is true.
获取或重置给定事件的尝试次数。
$ipLimiter->event('123.123.0.1', 'sendmail'); $ipLimiter->log(); $ipLimiter->log(); $attempts = $ipLimiter->attempts(); // Returns 2. $ipLimiter->resetAttempts(); // Sets value to 0.
获取或重置上次尝试以来时间。
$ipLimiter->event('123.123.0.1', 'sendmail'); $ipLimiter->log(); $lastTime = $ipLimiter->last(false); // Returns the unix epoc time since last attempt. $lastSeconds = $ipLimiter->last(); // Returns the # of seconds since last attempt.
注意:您无法重置上次尝试以来时间。如果数据库中存在该事件的记录,则它有一个时间戳。为了解决这个问题,只需完全删除事件即可,这相当于'永远'。
删除事件。
$ipLimiter->event('123.123.0.1', 'sendmail'); $ipLimiter->log(); $ipLimiter->deleteEvent();
删除给定IP的所有事件。
此函数不需要设置事件,而是传入IP地址。
$result = $ipLimiter->deleteIP('123.123.0.1'); // Returns false if no records were found/deleted. True otherwise.
管理事件的禁用状态。
注意,使用此方法,IP被禁止访问事件的具体类别,而不是系统范围内的禁止。ban/unBan方法返回当前的禁用状态,而不是ban/unban设置是否成功。
$ipLimiter->event('123.123.0.1', 'sendmail'); $ipLimiter->log(); $status = $ipLimiter->isBanned(); // Returns false, ie not currently banned. $status = $ipLimiter->ban(); // Now true, ie is currently banned. $status = $ipLimiter->unBan(); // Now false, ie not currently banned.
规则
IPLimiter的核心功能是运行事件对规则集的测试,以查看是否通过。这样,您的应用程序可以为各种操作类别有不同的规则。以下是一个示例
规则示例:发送邮件
在我们的应用程序中,用户每5分钟(300秒)最多只能发送一次邮件。在重置时间之前,他们最多可以尝试发送邮件3次。对于此规则集,禁用状态很重要(即某些事件可能使用禁用状态用于其他目的,但不用于规则)。在1小时(3600秒)没有尝试后,尝试次数将被重置。
我们的规则集以JSON格式表示
{
"resetAtSeconds": 3600,
"waitAtLeast": 300,
"allowedAttempts": 3,
"allowBanned":false
}
这意味着
- 如果数据库中不存在记录,则通过。
- 如果上次尝试是在3600秒之前或更早,则重置尝试次数为0。
- 如果上次尝试是在300秒之前或更近,则失败。
- 如果当前尝试次数超过3,则失败。
- 如果被禁止,则失败。
- 否则,通过。
执行当前设置的事件的规则集(将失败)
$ipLimiter->event('111.222.333.444', 'sendmail'); $ipLimiter->log(); // User sent first mail. $ruleResult = $ipLimiter->rule('{ "resetAtSeconds":3600, "waitAtLeast":300, "allowedAttempts":3, "allowBanned":false }'); // $ruleResult is false because there was NO time since the last (log) event.
执行当前设置的事件的规则集(将通过)
$ipLimiter->event('111.222.333.444', 'sendmail'); $ipLimiter->log(); // User sent first mail. $ruleResult = $ipLimiter->rule('{ "resetAtSeconds":3600, "waitAtLeast":-1, "allowedAttempts":3, "allowBanned":false }'); // $ruleResult is true because -1 means ignore time since last event, and only look at attempts. 1 <= 3 so PASS.
提示:规则集的"resetAtSeconds"、"waitAtLeast"和"allowedAttempts"部分可以设置为-1以忽略此部分。
贡献
- 欢迎并感谢拉取请求!请耐心等待我找到时间进行审查。
- 捐赠: https://github.com/syntaxseed#donatecontribute
变更日志
- v2.0.3 - 测试通过 PHP 8.1。
- v2.0.2 - 测试通过 PHP 8.0,修复 PSR 格式。
- v2.0.0 - IPLimiter 现在期望一个实现了 included DatabaseInterface 的数据库对象。包含了一个 PDO 实现。注意:由于数据库列类型变更,不兼容版本 1。
- v1.0.4 - 向 README 添加截图。
- v1.0.3 - 允许在 event() 和 log() 方法上使用方法链。
- v1.0.2 - 改进 README。更好的包描述。
- v1.0.1 - 修复 README。
- v1.0.0 - 初始发布。
