本文主题:RESTful的频率限制(Rate Limiting)
要阻止被滥用,你可以考虑在在API中添加limiting。例如,你可能想要限制API的使用为:每个用户在10分钟内最多有100次API调用,如果在限制的时间段内接收到一个用户太多的请求,带有429状态(意思是"请求次数过多")的响应将被返回。
要使用频率限制生效,用户标识类(user identity class)将实现yii\filters\RateLimitInterface接口,此接口需要实现三个方法:
1、getRateLimit():返回允许请求的最大次数和时间周期(例如,[100,600]意思是在600秒内最多有100次API调用)
2、loadAllowance():返回限制频率最后一次检测时剩余的请求次数和相应的UNIX时间戳
3、saveAllowance():保存剩余的请求次数和当前的UNIX时间戳

你可能需要在用户表中定义两列来记录限额(allowance)和时间戳信息,定义好后,loadAllowance()和saveAllowance()用于读取和存储当前认证用户的两列值。为了提高性能,你可以考虑将这些信息存储在缓存或NoSQL存储体中。

在User模型中的实现代码如下:

public function getRateLimit($request, $action)
{
return [$this->rateLimit, 1]; // $rateLimit requests per second
}

public function loadAllowance($request, $action)
{
return [$this->allowance, $this->allowance_updated_at];
}

public function saveAllowance($request, $action, $allowance, $timestamp)
{
$this->allowance = $allowance;
$this->allowance_updated_at = $timestamp;
$this->save();
}
一旦标识类实现了相应的接口,Yii将自动使用配置为yii\rest\Controller的动作过滤器的yii\filters\RateLimiter来执行频率检查,当频率超限时,频率限制器将抛出一个yii\web\TooManyRequestsHttpException异常。

你可以在REST控制器类中按如下方式配置频率限制:

public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['rateLimiter']['enableRateLimitHeaders'] = false;
return $behaviors;
}
当频率限制有效时,响应将被发送,默认在每个响应中包含当前频率限制的头信息:
X-Rate-Limit-Limit, 在时间周期内最大的请求允许数量
X-Rate-Limit-Remaining, 在当前时间周期内剩余的请求数量
X-Rate-Limit-Reset, 获取最大请求允许数需要等待的秒数
你可以设置yii\filters\RateLimiter::$enableRatelimitHeaders 为false来禁用这些头信息,前述代码中有示例。