eforce/throttle

(API) 在 CakePHP 中限制请求速率

安装: 3

依赖: 0

建议者: 0

安全: 0

星标: 0

关注者: 1

分支: 0

开放问题: 0

类型:cakephp-plugin

1.0 2023-09-14 12:06 UTC

This package is auto-updated.

Last update: 2024-09-14 14:55:43 UTC


README

Build Status Coverage Status Total Downloads License

(API) 在 CakePHP 中限制请求速率

此插件允许您限制客户端在特定时间范围内对您的应用程序发起请求的次数。

安装

composer require muffin/throttle

要使您的应用程序加载此插件,请运行

./bin/cake plugin load Muffin/Throttle

配置

在您的 config/app.php 中,在 Cache 键下添加名为 throttle 的缓存配置,并添加所需的配置。例如:

'throttle' => [
    'className' => 'Apcu',
    'prefix' => 'throttle_'
],

使用中间件

将中间件添加到队列中,并传递您的自定义配置

public function middleware(MiddlewareQueue $middlewareQueue): MiddlewareQueue
{
    // Various other middlewares for error handling, routing etc. added here.

    $throttleMiddleware = new \Muffin\Throttle\Middleware\ThrottleMiddleware([
        // Data used to generate response with HTTP code 429 when limit is exceeded.
        'response' => [
            'body' => 'Rate limit exceeded',
        ],
        // Time period as number of seconds
        'period' => 60,
        // Number of requests allowed within the above time period
        'limit' => 100,
        // Client identifier
        'identifier' => function ($request) {
            if (!empty($request->getHeaderLine('Authorization'))) {
                return str_replace('Bearer ', '', $request->getHeaderLine('Authorization'));
            }

            return $request->clientIp();
        }
    ]);

    $middlewareQueue->add($throttleMiddleware);

    return $middlewareQueue;
}

上面的示例将允许每分钟/令牌100次请求,并首先尝试通过 JWT Bearer 令牌识别客户端,然后回退到基于 IP 地址的识别。

事件

中间件还会触发以下事件,从而允许您具有多个速率限制

Throttle.beforeThrottle

这是在中间件处理请求之前首先触发的事件。如果停止此事件,则所有速率限制过程将被绕过。

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_THROTTLE,
    function ($event, $request) {
        if (/* check for something here, most likely using $request */) {
            $event->stopPropogation();
        }
    }
);

Throttle.getIdentifier

除了使用 identifier 配置之外,您还可以为 Throttle.getIdentifier 事件设置监听器。事件的回调函数将接收一个请求实例作为参数,并必须返回一个标识符字符串。

Throttle.getThrottleInfo

Throttle.getThrottleInfo 事件允许您根据请求自定义 periodlimit 配置,以及存储速率限制信息的缓存键。

这允许您根据应用程序的需求设置多个速率限制。

以下是一个示例

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_GET_THROTTLE_INFO,
    function ($event, $request, \Muffin\Throttle\ValueObject\ThrottleInfo $throttle) {
        // Set a different period for POST request.
        if ($request->is('POST')) {
            // This will change the cache key from default "{identifer}" to "{identifer}.post".
            $throttle->appendToKey('post');
            $throttle->setPeriod(30);
        }

        // Modify limit for logged in user
        $identity = $request->getAttribute('identity');
        if ($identity) {
            $throttle->appendToKey($identity->get('role'));
            $throttle->setLimit(200);
        }
    }
);

Throttle.beforeCacheSet

Throttle.beforeCacheSet 事件允许您观察中间件配置以及先前 Throttle.getIdentifierThrottle.getThrottleInfo 事件的结果。

您还可以使用此事件修改缓存的 $rateLimit$ttl 值,在此事件中修改 $throttleInfo 没有作用。

示例

\Cake\Event\EventManager::instance()->on(
    \Muffin\Throttle\Middleware\ThrottleMiddleware::EVENT_BEFORE_CACHE_SET,
    function ($event, \Muffin\Throttle\ValueObject\RateLimitInfo $rateLimit, int $ttl, \Muffin\Throttle\ValueObject\ThrottleInfo $throttleInfo) {
        \Cake\Log\Log::debug(sprintf("key(%s) remaining(%d) resetTimestamp(%d) ttl(%d)", $throttleInfo->getKey(), $rateLimit->getRemaining(), $rateLimit->getResetTimestamp(), $ttl));
    }
);

X-headers

默认情况下,Throttle 会将包含速率限制信息的 X-headers 添加到所有响应中

X-RateLimit-Limit: 10
X-RateLimit-Remaining: 7
X-RateLimit-Reset: 1438434161

要自定义头名称,只需在配置数组中 headers 键下传递(所有)即可

'headers' => [
    'limit' => 'X-MyRateLimit-Limit',
    'remaining' => 'X-MyRateLimit-Remaining',
    'reset' => 'X-MyRateLimit-Reset',
]

要禁用头,将 headers 键设置为 false

自定义响应对象

如果您想返回不同的消息,而不是默认消息,可以使用 response 数组的 typeheaders 子键(就像使用 Response 对象一样)。

new \Muffin\Throttle\Middleware\ThrottleMiddleware([
    'response' => [
        'body' => json_encode(['error' => 'Rate limit exceeded']),
        'type' => 'json',
        'headers' => [
            'Custom-Header' => 'custom_value',
        ]
    ],
    'limit' => 300,
]);

补丁和功能

  • 分支
  • 修改、修复
  • 测试 - 这很重要,所以它不会被意外破坏
  • 提交 - 不要修改许可证、todo、版本等。(如果进行了更改,请将它们提升为单独的提交,以便我在拉取时可以忽略它们)
  • 拉取请求 - 主题分支的额外积分

为确保您的 PR 被考虑,您必须遵循 CakePHP 编码标准。

错误和反馈

http://github.com/usemuffin/throttle/issues

许可证

版权所有 (c) 2015-现在,[Use Muffin] 并在 MIT 许可证 下许可。