专栏名称: 4Ark
前端
目录
相关文章推荐
51好读  ›  专栏  ›  4Ark

Lumen 使用 throttle 限制接口访问频率

4Ark  · 掘金  · Javascript  · 2019-01-21 04:46

正文

请到「今天看啥」查看全文


阅读 124

Lumen 使用 throttle 限制接口访问频率

前言

今天碰到过这样一个情况,我需要限制用户请求某个 API 接口的频率,比如登录、反馈等提交操作,经过一番搜索+折腾,总算是实现了。

Laravel 5.2 的新特性中增加了一个 throttle 中间件,通过它可以在路由层限制 API 访问的频率。例如限制频率为1分钟50次,如果一分钟内超过了这个限制,它就会响应:429: Too Many Attempts。

但我在项目中使用的是 Lumen 框架(它只有 Laravel 中的一部分功能),它并没有集成这个中间件,所以本文主要是讲述如何在 Lumen 框架中加入 throttle 中间件。

开始

首先我们要在 app\Http\Middleware 中新建 ThrottleRequests.php 文件。

并且把以下链接中的代码拷贝到这个文件中:

github.com/illuminate/…

接着修改文件中的命名空间:

namespace App\Http\Middleware;
复制代码

标记同一用户端请求

因为 Lumen 框架缺失部分功能,我们需要修改 ThrottleRequests.php 中的 resolveRequestSignature 方法:

protected function resolveRequestSignature($request){
    return sha1(
        $request->method() .
        '|' . $request->server('SERVER_NAME') .
        '|' . $request->path() .
        '|' . $request->ip()
    );
}
复制代码

抛出响应

throttle 超过限制时抛出的是 Illuminate\Http\Exceptions\ThrottleRequestsException ,同样 Lumen 框架缺少这个文件,需要自己定义一下,在 app/Exceptions 中新建 ThrottleException.php ,写入以下代码:

<?php

namespace App\Exceptions;

use Exception;

class ThrottleException extends Exception{
    protected $isReport = false;

    public function isReport(){
        return $this->isReport;
    }
}
复制代码

app/Exceptions/Handler.php 捕获该抛出异常,在 render 方法增加以下判断:

if ($exception instanceof ThrottleException) {
	return response([
        'code' => $exception->getCode(),
        'msg' => $exception->getMessage()
	], 429);
}
复制代码

修改 ThrottleRequests.php 文件中的 buildException 方法:

protected function buildException($key, $maxAttempts){
	$retryAfter = $this->getTimeUntilNextRetry($key);
	$headers = $this->getHeaders(
        $maxAttempts,
        $this->calculateRemainingAttempts($key, $maxAttempts, $retryAfter),
        $retryAfter
    );
    // 修改了这一行
  	return new ThrottleException('Too Many Attempts.', 429);
}
复制代码

需在文件头部中添加这一行: use App\Exceptions\ThrottleException;

注册中间件

bootstrap/app.php 中注册:

$app->routeMiddleware([
     'throttle' => App\Http\Middleware\ThrottleRequests::class,
]);
复制代码

到这里我们就加入成功了,接着在路由中添加中间件即可:

 $router->group(['middleware' => ['throttle:10,2']],function() use ($router){

	$router->post('feedback','UserController@addFeedback');

});
复制代码

其中 throttle:10,2 表示的是2分钟内访问10次。

注:此文为原创文章,如需转载,请注明出处。







请到「今天看啥」查看全文