beheh / flaps
应用于应用程序中请求速率限制的模块化库
Requires
- php: >=5.3.0
Requires (Dev)
- doctrine/cache: ~1.4
- phpunit/phpunit: ~4.0
- predis/predis: ~1.0
Suggests
- doctrine/cache: Enables a wide variety of caching systems as storage
- predis/predis: Enable Redis as storage system
This package is auto-updated.
Last update: 2023-10-06 22:27:18 UTC
README
Flaps是一个针对PHP应用程序中请求速率限制的模块化库。
该库支持自定义存储后端、节流策略和违规处理器,以便灵活地集成到任何项目中。
由@beheh开发并许可使用ISC许可证。
要求
- PHP 5.4或更高版本
- 持久的存储(例如Redis、APC或由Doctrine Cache支持的任何存储)
- Composer
基本用法
use Predis\Client; use BehEh\Flaps\Storage\PredisStorage; use BehEh\Flaps\Flaps; use BehEh\Flaps\Throttling\LeakyBucketStrategy; // setup with Redis as storage backend $storage = new PredisStorage(new Client()); $flaps = new Flaps($storage); // allow 3 requests per 5 seconds $flaps->login->pushThrottlingStrategy(new LeakyBucketStrategy(3, '5s')); //or $flaps->__get('login')->pushThrottlingStrategy(...) // limit by ip (default: send "HTTP/1.1 429 Too Many Requests" and die() on violation) $flaps->login->limit($_SERVER['REMOTE_ADDR']);
为什么需要速率限制?
对您的Web应用程序进行速率限制有许多好处。在任何时候,您的服务器都可能受到来自一个或多个客户端的大量请求的攻击。这些可能包括
- 恶意客户端试图降低您的应用程序性能
- 恶意客户端暴力破解用户凭据
- 有缺陷的客户端反复请求
- 自动化的网络爬虫枚举用户名或电子邮件地址
- 渗透框架测试漏洞
- 机器人注册大量用户
- 机器人散布指向恶意网站的链接
大多数这些问题都可以通过多种方式解决,例如使用垃圾邮件过滤器或完全配置的防火墙。然而,速率限制是提高应用程序安全性的基本工具,但并不提供完全保护。
高级示例
应用程序处理的违规
use BehEh\Flaps\Throttling\LeakyBucketStrategy; use BehEh\Flaps\Violation\PassiveViolationHandler; $flap = $flaps->__get('api'); $flap->pushThrottlingStrategy(new LeakyBucketStrategy(15, '10s')); $flap->setViolationHandler(new PassiveViolationHandler); if (!$flap->limit(filter_var(INPUT_GET, 'api_key'))) { die(json_encode(array('error' => 'too many requests'))); }
多种节流策略
use BehEh\Flaps\Throttling\LeakyBucketStrategy; $flap = $flaps->__get('add_comment'); $flap->pushThrottlingStrategy(new LeakyBucketStrategy(1, '30s')); $flap->pushThrottlingStrategy(new LeakyBucketStrategy(10, '10m')); $flap->limit($userid);
存储
Redis
最容易启动的存储系统是Redis(通过nrk/predis)
use Predis\Client; use BehEh\Flaps\Storage\PredisStorage; use BehEh\Flaps\Flaps; $storage = new PredisStorage(new Client('tcp://10.0.0.1:6379')); $flaps = new Flaps($storage);
不要忘记composer require predis/predis
。
Doctrine缓存
您可以通过使用DoctrineCacheAdapter来使用任何Doctrine缓存实现。
use Doctrine\Common\Cache\ApcCache; use BehEh\Flaps\Storage\DoctrineCacheAdapter; use BehEh\Flaps\Flaps; $apc = new ApcCache(); $apc->setNamespace('MyApplication'); $storage = new DoctrineCacheAdapter($apc); $flaps = new Flaps($storage);
可以使用composer require doctrine/cache
安装Doctrine缓存实现。
自定义存储
或者,您可以通过实现BehEh\Flaps\StorageInterface来使用您自己的存储系统。
节流策略
漏桶策略
此策略基于漏桶算法。每个flaps的唯一标识符对应一个漏桶。客户端现在可以尽可能多地访问桶,为每个请求插入水。如果请求会导致桶溢出,则拒绝。为了允许后续请求,桶以固定速率漏水。
use BehEh\Flaps\Throttle\LeakyBucketStrategy; $flap->pushThrottlingStrategy(new LeakyBucketStrategy(60, '10m'));
自定义节流策略
同样,您可以通过实现BehEh\Flaps\ThrottlingStrategyInterface来提供自己的节流策略。
违规处理器
您可以使用包含的处理器之一或编写自己的处理器来处理违规。
HTTP违规处理器
HTTP违规处理器是最基本的违规处理器,适用于简单的脚本。它简单地发送正确的HTTP头(状态码429)并退出。这不推荐用于任何大型应用程序,应替换为更可定制的处理器之一。
use BehEh\Flaps\Violation\HttpViolationHandler; $flap->setViolationHandler(new HttpViolationHandler); $flap->limit($identifier); // send "HTTP/1.1 429 Too Many Requests" and die() on violation
被动违规处理器
被动违规处理器允许您轻松地对违规做出反应。如果请求违反了任何节流策略,则limit()
将返回false,因此您可以记录请求或返回自定义错误页面。
use BehEh\Flaps\Violation\PassiveViolationHandler; $flap->setViolationHandler(new PassiveViolationHandler); if (!$flap->limit($identifier)) { // violation }
异常违规处理器
异常违规处理程序可以在更大的框架中使用。每当违反了ThrottlingStrategy时,它将抛出一个ThrottlingViolationException。您应该能够设置您的异常处理程序以捕获任何ThrottlingViolationException。
use BehEh\Flaps\Violation\ExceptionViolationHandler; use BehEh\Flaps\Violation\ThrottlingViolationException; $flap->setViolationHandler(new ExceptionViolationHandler); try { $flap->limit($identifier); // throws ThrottlingViolationException on violation } catch (ThrottlingViolationException $e) { // violation }
自定义违规处理程序
自定义违规处理程序的相应接口是BehEh\Flaps\ViolationHandlerInterface。
默认违规处理程序
Flaps
对象可以将默认违规处理程序传递给flaps。
$flaps->setDefaultViolationHandler(new CustomViolationHandler); $flap = $flaps->__get('login'); $flap->addThrottlingStrategy(new TimeBasedThrottlingStrategy(1, '1s')); $flap->limit($identifier); // will use CustomViolationHandler