beheh/flaps

此包已被废弃,不再维护。未建议替代包。

应用于应用程序中请求速率限制的模块化库

0.2.0 2017-06-02 21:56 UTC

This package is auto-updated.

Last update: 2023-10-06 22:27:18 UTC


README

Travis Scrutinizer Coverage Scrutinizer Packagist Packagist

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