jalismrs / gentle-force
此包已被废弃且不再维护。未建议替代包。
基于Redis,使用漏桶/令牌桶算法限制暴力破解尝试和普通请求的库
0.4.0
2021-04-20 14:32 UTC
Requires
- php: ^5.5 | ^7.0 | ^8.0
- predis/predis: ^1.1
Requires (Dev)
- friendsofphp/php-cs-fixer: ^2.2
- misterion/ko-process: ^0.5.3
- phpunit/phpunit: ^4.8.36
- sebastian/comparator: ^1.2.4
- symfony/stopwatch: ^3.2
This package is not auto-updated.
Last update: 2024-05-16 04:21:19 UTC
README
这是一个限制暴力破解尝试(如无效凭证)和普通请求的库。
特性
- 可用于限制暴力破解尝试;
- 可用于请求速率限制;
- 使用漏桶/令牌桶算法。这意味着用户不需要等待下一个小时或一天 - 随着时间的推移,额外的尝试是可能的。这也意味着请求不会在每小时开始时大批量到达;
- 处理竞争条件。这对于暴力破解限制很重要。例如,如果有1000个请求同时发出以检查同一用户的密码,则只能进行配置的数量尝试;
- 可以为单个用例配置多个限制(例如,每分钟最多100次请求和每小时200次);
- 不对使用位置和用途做任何假设 - 可以与用户标识符、API令牌、IP地址或其他任何数据一起使用以分组使用。
安装
composer require maba/gentle-force
使用方法
<?php use Maba\GentleForce\RateLimit\UsageRateLimit; use Maba\GentleForce\RateLimitProvider; use Maba\GentleForce\Throttler; use Maba\GentleForce\Exception\RateLimitReachedException; $rateLimitProvider = new RateLimitProvider(); $rateLimitProvider->registerRateLimits('credentials_error', [ // allow 3 errors per hour; 2 additional errors if no errors were made during last hour (new UsageRateLimit(3, 3600))->setBucketedUsages(2), // allow 10 errors per day new UsageRateLimit(10, 3600 * 24), ]); $rateLimitProvider->registerRateLimits('api_request', [ // - allow 10 requests each minute; // - user can "save up" hour of usage if not using API. // This means up to 610 requests at once, after that - 10 requests per minute, // which could again save-up up to 610. (new UsageRateLimit(10, 60))->setBucketedPeriod(3600), ]); $throttler = new Throttler(new \Predis\Client([ 'host' => '127.0.0.1', ]), $rateLimitProvider); // rate limiting: try { $result = $throttler->checkAndIncrease('api_request', $_SERVER['REMOTE_ADDR']); header('Requests-Available', $result->getUsagesAvailable()); } catch (RateLimitReachedException $exception) { header('Wait-For', $exception->getWaitForInSeconds(), 429); return; } // brute-force limiting: try { // we must increase error count in-advance before even checking credentials // this avoids race-conditions with lots of requests $credentialsResult = $throttler->checkAndIncrease('credentials_error', $_POST['username']); } catch (RateLimitReachedException $exception) { echo sprintf('Too much password tries for user. Please try after %s seconds', $exception->getWaitForInSeconds()); return; } $credentialsValid = checkCredentials($_POST['username'], $_POST['password']); if ($credentialsValid) { // as we've increased error count in advance, we need to decrease it if everything went fine $credentialsResult->decrease(); // log user into system }
替代方案
实际上,有很多这样的方案。
不幸的是,由于一些方案提供了额外的功能(如不同的存储方法:文件、memcached等),没有找到符合这些标准的方案
- 仅用于暴力破解(仅在错误时),不用于所有请求;
- 抽象的,以便可以通过用户、IP和其他标识符进行限制;
- 速率限制算法不会长时间阻塞合法用户;
- 在高峰负载下,实际的限制不会因为竞争条件而无法正确工作。
以下是一些已审查的替代方案:RateLimitInterface、rate-limiter、LosRateLimit、Rate-limit、rate-limit、php-ratelimiter、tokenbucket、brute-force、LoginGateBundle、tresholds-governor、throttle、PeerjUserSecurityBundle、php-ratelimiter、RateLimitBundle、CybBotDetectBunble、CCDNUserSecurityBundle、limit-number-calls-bundle、rate-limiter-php、flaps、token-bucket
语义化版本控制
此库遵循语义化版本控制。
有关API中可以更改和不可以更改的基本信息,请参阅Symfony BC规则。
运行测试
功能测试需要Redis和多个PHP扩展,以便能够测试高流量下的行为。因此,通常在docker中运行它们更容易。
composer update
cd docker
docker-compose up -d
docker exec -it gentle_force_test_php vendor/bin/phpunit
docker-compose down
贡献
请随意创建问题和提供拉取请求。
您可以使用此命令修复任何代码风格问题
vendor/bin/php-cs-fixer fix --config=.php_cs