eddiejibson / limitrr-php
使用redis进行更好的PHP速率限制。
1.0.0
2018-12-21 19:28 UTC
Requires
- predis/predis: ^1.1
This package is auto-updated.
Last update: 2024-09-18 06:13:42 UTC
README
在PHP中使用Redis实现轻量级速率限制。
Limitrr PHP深受我的其他库Limitrr的启发,该库是为NodeJS创建的。请在这里查看这里
Limitrr PHP允许用户轻松地将速率限制集成到其应用程序中。与其他类似包不同,此实用工具不仅允许用户按请求数量限制,还可以按完成的操作数量(例如,在一定时间内允许成功创建一定数量的账户)进行限制,并且可以使用自定义选项进行限制。此外,还可以使用自定义区分器 - 您不再只能通过用户的IP进行限制。
此库还提供了一种中间件函数,可以轻松地对SlimPHP项目中的任何各种路由进行速率限制。
如果您喜欢这个项目,请🌟在GitHub上给它评分。
欢迎提交拉取请求
安装
您可以通过在终端中执行以下命令来安装limitrr-php库(假设您已安装composer 已安装)
composer require eddiejibson/limitrr-php "^1.0"
快速指南
基本用法
require "/vendor/autoload.php"; //Require composer's autoload $options = [ //Redis keystore information "redis" => [ "host" => "666.chae.sh", "port" => 6379, "password" => "supersecret", ], "routes" => [ "default" => [ "requestsPerExpiry" => 5, ], ], ]; //Initialize the Limitrr class and pass the options defined above into it //Note that the options are not required. $limitrr = new \eddiejibson\limitrr\Limitrr($options); //Various examples like this can be found further into the documentation, //for each function. $result = $limitrr->get(["discriminator" => $ip]); echo $result["requests"] + " Requests"; echo $result["completed"] + " Completed"; //Note that this library is no means just for SlimPHP, it just happens to //provide a middleware function for those who may need it. //Usage within SlimPHP $app = new Slim\App(); //Use the Limitrr SlimPHP middleware function, if you wish: $app->add(new \eddiejibson\limitrr\RateLimitMiddleware($limitrr)); //Make sure to pass in the main Limitrr //instance we defined above into the middleware function. This is mandatory. //You can also add the get IP middleware function, it will append the user's real IP //(behind Cloudflare or not) to the request. $app->add(new \eddiejibson\limitrr\getIpMiddleware()); //Example usage within a route $app->get("/hello/{name}", function ($request, $response, $args) { $name = $args["name"]; $ip = $request->getAttribute('realip'); //Get the IP that was defined within Limitrr's get IP middleware function return $response->getBody()->write("Hello, ${name}. Your IP is ${ip}."); }); //You do not have to app the middleware function to every single route, globally. //You can do it indivually, too - along with passing options into such. Like so: $app->get("/createUser/{name}", function ($request, $response, $args) { //Non intensive actions like simple verification will have a different limit to intensive ones. //and will only be measured in terms of each request via the middleware. //No further action is required. if (strlen($args["name"]) < 5) { //Dummy function creating user $res = $someRandomClass->registerUser(); if ($res) { //Intensive actions like actually registering a user should have a //different limit to normal requests, hence the completedActionsPerExpiry option. //and should only be added to once this task has been completed fully //In this example, we will be limiting the amount of completed actions a certain IP can make. //Anything can be passed in here, however. For example, a email address or user ID. //$request->getAttribute('realip') was determined by calling the middleware earlier - getIpMiddleware() $limitrr->complete(["discriminator"] => $ip); } } })->add(new \eddiejibson\limitrr\RateLimitMiddleware($limitrr, ["route"=>"createUser"])); //You can also pass the route name within the limitrr middleware function $app->run();
获取某个键的值
limitrr->get()
返回: Array
$limitrr->get([ "discriminator" => $discriminator, //Required "route" => $route, //Not required, default is assumed "type" => $type //Not required ]);
->get() 参数
必须通过数组传递到函数中
- 区分器: 必需 区分器是限制的东西(例如,每个区分器的x个完成的操作)
- 路由: String 应从哪个路由检索值?如果未设置,将从
default
路由获取计数 - 类型: String 您可以指定此键中的
requests
或completed
,而不是检索两个值,只返回整数。
->get() 示例
$limitrr->get([ "discriminator" => $discriminator, "type" => $type, "route" => $route ]); //Besides discriminator, all parameters are optional. //If type is not passed into the function, it will //return both the amount of requests and completed actions //Where discriminator is the thing being limited //e.g x amount of completed actions/requests per discriminator $limitrr->get(["discriminator" => $discriminator]); //This tends to be the user's IP. $limitrr->get(["discriminator" => $ip]); //This will return both the amount of requests and completed actions stored under the //discriminator provided in an object. You can handle like this: $result = $limitrr->get(["discriminator" => $ip]); echo $result["requests"] + " Requests"; echo $result["completed"] + " Completed"; //The above example would get the request and completed task count from the default //route. If you would like to retrieve values from a different route, you can specify //this as well. It can be done like this: $result = $limitrr->get(["discriminator" => $ip, "route" => "exampleRouteName"]); echo $result["requests"] . " Requests made through the route exampleRouteName"; echo $result["completed"] . " Completed Tasks made through the route exampleRouteName"; //You may also only fetch only one type of value - instead of both requests and completed. $result = $limitrr->get(["discriminator" => $ip, "route" => "exampleRouteName", "type" => "completed"]); echo $result["completed"] . " Completed tasks made through the route exampleRouteName";
完成操作/任务计数
limitrr->complete()
返回: Integer
$limitrr->get([ "discriminator" => $discriminator, //Required "route" => $route, //Not required, default is assumed ]);
->complete() 参数
必须通过数组传递到函数中
- 区分器: 必需 区分器是限制的东西(例如,每个区分器的x个完成的操作)
- 路由: String 应将值插入到哪个路由中?如果未设置,将从
default
路由获取计数
从某些请求/完成键中删除值
limitrr->reset()
返回: Boolean
$limitrr->reset([ "discriminator" => $discriminator, //Required "route" => $route, //Not required, default is assumed, "type" => $type //Not required ]);
->reset() 参数
必须通过数组传递到函数中
- 区分器: 必需 区分器是限制的东西(例如,每个区分器的x个完成的操作)
- 路由: String 应从哪个路由中重置值?如果未设置,将从
default
路由重置计数 - 类型: String 您希望重置哪个计数?
requests
或completed
?如果未设置,则删除两个计数。
//Where discriminator is the thing being limited //e.g x amount of completed actions/requests per discriminator //This will remove both the amount of requests and completed action count $limitrr->reset(["discriminator" => $discriminator]); //This tends to be the user's IP. $limitrr->reset(["discriminator" => $ip]); //If you wish to reset counts from a particular route, this can be done as well. //As the type is not specified, it will remove both the request and completed count $result = $limitrr->reset([ "discriminator" => $ip, "route" => "exampleRouteName" ]); if ($result) { echo "Requests removed from the route exampleRouteName"; } else { //Do something else } //If you want to remove either one of the amount of requests or completed actions. //but not the other, this can be done as well. //The value passed in can either be "requests" or "completed". //In this example, we will be removing the request count for a certain IP $result = $limitrr->reset([ "discriminator" => $ip, "type" => "requests" ]); if ($result) { echo "Request count for the specified IP were removed" } else { //do something else }
配置
redis
必需: false
类型: Array OR String
描述: Redis连接信息。
传递包含redis实例URI的字符串或包含连接信息的对象
- 端口: Integer Redis端口。默认为:
6379
- 主机: String Redis主机名。默认为:
"127.0.0.1"
- 密码: String Redis密码。默认为:
""
- 数据库: Integer Redis DB。默认为:
0
可以传递给Limitrr的redis数组/字符串示例
//Pass in a string containing a redis URI. "redis" => "redis://127.0.0.1:6379/0" //Alternatively, use an array with the connection information. "redis" => [ "port" => 6379, //Redis Port. Required: false. Defaults to 6379 "host" => "127.0.0.1", //Redis hostname. required: False. Defaults to "127.0.0.1". "password" => "mysecretpassword1234", //Redis password. Required: false. Defaults to null. "database" => 0 //Redis database. Required: false. Defaults to 0. ]
options
必需: false
类型: Array
描述: 与Limitrr相关的各种选项。
- keyName: String 所有请求都将存储在此键名下。这主要出于美观目的,不会影响太多。但是,应该在每个主类的初始化时更改,以防止冲突。默认为:
"limitrr"
- errorStatusCode: 当用户被限流时返回的整数状态码。默认为
429
(请求过多)
Limitrr 可能接收的选项对象示例
"options" => [ "keyName" => "myApp", //The keyname all of the requests will be stored under. Required: false. Defaults to "limitrr" "errorStatusCode" => 429 //Should important errors such as failure to connect to the Redis keystore be caught and displayed? ]
路由
必填:否
类型:数组
描述:定义路由限制。
在路由对象内部,您可以定义多个单独的路由,并在其中设置自定义规则。您可以设置的自定义规则包括
- requestsPerExpiry:整数 用户被限流前可以接受多少次请求?默认为:
100
- completedActionsPerExpiry:整数 用户被限流前可以接受多少次完成操作?这对于某些操作(如注册用户)非常有用,他们可以有特定数量的请求,但“完成操作”的数量(显然更少)。因此,如果用户在相同的IP(或其他区分器)下最近成功注册多次,他们可能会被限流。他们可能每期被允许100次请求进行一般验证等,但对于密集型流程,只有一小部分。默认值与
requestsPerExpiry
相同,如果没有设置,则为5
。 - expiry:整数 请求存储多长时间(以秒为单位)后将被重置为0?如果设置为 -1,则值将永远不会过期并无限期保持,或必须手动删除。默认为:
900
(15分钟) - completedExpiry:整数 "完成操作"(如来自特定IP或其他区分器的用户注册数量)存储多长时间(以秒为单位)后将被重置为0?如果设置为 -1,则此类值将永远不会过期并无限期保持,或必须手动删除。默认值与
expiry
相同,如果没有设置,则为900
(15分钟)。 - errorMsgs:对象 对于请求过多和完成操作过多分别设置的错误消息。它们分别被赋予了“requests”和“actions”的键名。当用户被限流时,这些消息将被返回给用户。如果没有在
requests
中设置字符串,则默认为"由于您请求过多,您正在被限流。"
。此外,如果没有在completed
中设置值,则将解析为在requests
中找到的字符串。如果没有设置该字符串,则默认为"由于您执行了过多成功操作,您已被限流。"
。
路由数组示例
"routes" => [ //Overwrite default route rules - not all of the keys must be set, //only the ones you wish to overwrite "default" => [ "expiry": 1000 ], "exampleRoute" => [ "requestsPerExpiry" => 100, "completedActionsPerExpiry" => 5, "expiry" => 900, "completedExpiry" => 900, "errorMsgs" => [ "requests" => "As you have made too many requests, you are being rate limited.", "completed" => "As you performed too many successful actions, you have been rate limited." ] ], //If not all keys are set, they will revert to //the default values "exampleRoute2" => [ "requestsPerExpiry" => 500 ] ]