实际上Laravel自带有访问控制路由中间件 throttle

默认是 throttle:60,1
就是限制同一个IP在1分钟60次请求,超出的会被拦截,下一分钟才会恢复访问,它没有黑名单和白名单的功能,需要自己重新实现。

存储方式同cache driver

关于throttle:
https://learnku.com/articles/20073
https://learnku.com/articles/27682
https://segmentfault.com/a/1190000013499082

此处的频率是任意接口的访问总和,如果想限制到每一个接口,则需要自己拷贝 throttle 重新实现了。

以下是自己写的中间件,可定制功能。

<?phpnamespace App\Http\Middleware;use Closure;use App\Traits\Controller\OpApiAjaxTraits;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;class GateWayPlus
{use  OpApiAjaxTraits;const IP_LIMIT_NUM_KEY = 'ipLimit:ipLimitNum';const IP_BLACK_LIST_KEY = 'ipLimit:ipBlackList';public $prefix = 'gateway';public $delaySeconds = 60; // 观察时间跨度,秒public $maxAttempts = 10000; // 限制请求数public $blackSeconds = 0; // 封禁时长,秒,0-不封禁/*** @param \Illuminate\Http\Request $request* @param Closure $next* @param int $maxAttempts* @param int $delaySeconds* @param int $blackSeconds* @param string $prefix* @return \App\Traits\Controller\json|mixed*/public function handle($request, Closure $next, $prefix = null, $delaySeconds = null, $maxAttempts = null, $blackSeconds = null){$path     = $request->path();$clientIp = $request->getClientIp();if (!is_null($prefix) && !empty($prefix)) {$this->prefix = $prefix;}// redis配置集群时必须$this->prefix = '{' . $this->prefix . '}';if (!is_null($maxAttempts)) {$this->maxAttempts = intval($maxAttempts);}if (!is_null($delaySeconds)) {$this->delaySeconds = intval($delaySeconds);}if (!is_null($blackSeconds)) {$this->blackSeconds = intval($blackSeconds);}$param  = ['path'     => $path,'clientIp' => $clientIp,];$result = $this->main($param);if ($result === false) {return $this->ajaxApiError('当前IP请求过于频繁,暂时被封禁~');}return $next($request);}private function main($param){// 预知的IP黑名单$blackList = [];if (in_array($param['clientIp'], $blackList)) {return false;}// 预知的IP白名单$whiteList = [];if (in_array($param['clientIp'], $whiteList)) {return true;}$blackKey = $this->prefix . ':' . self::IP_BLACK_LIST_KEY;$limitKey = $this->prefix . ':' . self::IP_LIMIT_NUM_KEY;$time = time();$item = md5($param['path'] . '|' . $param['clientIp']);return $this->luaScript($blackKey, $limitKey, $item, $time);}/** 普通模式*/public function normal($blackKey, $limitKey, $item, $time){if ($this->blackSeconds > 0) {$timeout = intval(Redis::hget($blackKey, $item));if ($timeout) {if ($timeout > $time) {// 未解封return false;}// 已解封,移除黑名单Redis::hdel($blackKey, $item);}}$last = intval(Redis::hget($limitKey, $item));if ($last >= $this->maxAttempts) {return false;}$num = Redis::hincrby($limitKey, $item, 1);if (Redis::ttl($limitKey) == -1) {Redis::expire($limitKey, $this->delaySeconds);}if ($num >= $this->maxAttempts && $this->blackSeconds > 0) {// 加入黑名单Redis::hset($blackKey, $item, $time + $this->blackSeconds);// 删除记录Redis::hdel($limitKey, $item);}return true;}/** LUA脚本模式* 支持redis集群部署*/public function luaScript($blackKey, $limitKey, $item, $time){$script = <<<'LUA'
local blackSeconds = tonumber(ARGV[5])
if(blackSeconds > 0)
thenlocal timeout = redis.call('hget', KEYS[1], ARGV[1])if(timeout ~= false)thenif(tonumber(timeout) > tonumber(ARGV[2]))thenreturn falseendredis.call('hdel', KEYS[1], ARGV[1])end
endlocal last = redis.call('hget', KEYS[2], ARGV[1])
if(last ~= false and tonumber(last) >= tonumber(ARGV[3]))
thenreturn false
endlocal num = redis.call('hincrby', KEYS[2], ARGV[1], 1)
local ttl = redis.call('ttl', KEYS[2])
if(ttl == -1)
thenredis.call('expire', KEYS[2], ARGV[4])
endif(tonumber(num) >= tonumber(ARGV[3]) and blackSeconds > 0)
then redis.call('hset', KEYS[1], ARGV[1], ARGV[2] + ARGV[5])redis.call('hdel', KEYS[2], ARGV[1])
end
return true
LUA;$result = Redis::eval($script, 2, $blackKey, $limitKey, $item, $time, $this->maxAttempts, $this->delaySeconds, $this->blackSeconds);if ($result) {return true;} else {return false;}}}

注册中间件

路由中的使用

$router->group(['namespace' => 'xxx', 'prefix' => 'yyy', 'middleware' => ['GateWayPlus:zzz,60,2,120']], function () use ($router) { }

Laravel项目IP黑名单,IP白名单,IP访问频率控制中间件相关推荐

  1. 网站通过nginx设置黑/白名单IP限制、国家城市IP访问限制

    一.黑/白名单IP限制访问配置 nginx配置黑白名单有好几种方式,这里只介绍常用的两种方法. 1.第一种方法:allow.deny deny和allow指令属于ngx_http_access_mod ...

  2. haproxy 客户端真实IP地址添加白名单

    haproxy 客户端真实IP地址添加白名单 haproxy 添加白名单的方法网上有了就不重复了: 我们的架构如下,haproxy 不是直接对外的,所以在haproxy添加ip地址白名单会限制所有交易 ...

  3. 钉钉授权时报获取钉钉用户信息失败,失败原因:访问ip不在白名单之中的解决办法

    前言 公司里的一个钉钉h5应用项目,进入里需要钉钉授权,提示:钉钉授权时报获取钉钉用户信息失败,失败原因:访问ip不在白名单之中的解决办法,这个错误有一段时间了,后来在官方的文档里找到解决方法 钉钉官 ...

  4. 微信白名单服务器ip地址,微信服务器白名单IP列表

    微信服务器白名单IP列表,列出以便自己做白名单使用. [0] => 101.226.62.77 [1] => 101.226.62.78 [2] => 101.226.62.79 [ ...

  5. 微信公众号白名单IP配置

    做微信公众号开发的时候就经常会需要配置白名单IP,但是很多人都不了解这个IP应该配置什么IP呢? 哪个服务放的代码调用公众号的接口,对应服务器的ip就是这个要配置的白名单IP了.

  6. 钉钉报错,访问ip不在白名单之中

    {"errcode":6***0,"errmsg":"请参考FAQ:https://open-doc.dingtalk.com/microapp/fa ...

  7. 自动分析黑名单及白名单的iptables脚本

    http://www.txwb.com/Article/serverHelp/gl/201005/70574.html  自动分析黑名单及白名单的iptables脚本 本文介绍的是一个自动分析黑名单和 ...

  8. 虚拟服务器添加用户白名单,apache配置黑名单和白名单及账户权限控制

    apache配置黑名单和白名单的两个方法 为项目需要,部署之后客户需要实现白名单功能.以前一般使用iis服务器或者是网上的DZ或CP面板,而且也仅仅操作过黑名单.百度搜索,基本都是黑名单的操作方法,本 ...

  9. 网络安全笔记--文件上传1(文件上传基础、常见后端验证、黑名单、白名单、后端绕过方式)

    1. 基础 1.1 初识文件上传漏洞 文件上传漏洞是一种非常严重的漏洞,如果Web没有对用户上传的文件进行有效地过滤,若有不法分子上传恶意脚本,就有可能获取执行服务端命令的能力,严重影响服务器安全. ...

最新文章

  1. Powershell管理系列(十)邮件联系人及邮件用户的管理
  2. 【从零学习OpenCV 4】Mat类构造与赋值
  3. C异常处理实现: setjmp和longjmp
  4. Windows PE 第八章 延迟加载导入表
  5. linux查看ko信息,linux 查看信息命令
  6. python queue查询空_【Python】多线程爬虫案例
  7. 极简风格的响应式简历模板
  8. 文本属性之装饰文本(CSS、HTML)
  9. [转精]IO_STACK_LOCATION与IRP的一点笔记
  10. ps色板文件怎么导入?
  11. 2022全国智慧医院建设大会会议通知
  12. 第三章:使用HiTool下载程序
  13. mfs java_mfs权威指南
  14. 两个路由器互连设置方法
  15. i59300h够用吗计算机网络技术,i5 9300H属于什么档次?看完跑分透心凉
  16. web前端不好找工作之web前端面试简历补救篇
  17. 什么是档案级光盘?它的寿命是多少年?
  18. VB编程编辑AutoCAD样条曲线
  19. 并发编程之循环屏障CyclicBarrier
  20. 自己设计的一个首尾相接js轮播图

热门文章

  1. 三个在线生成.ico图片的网站
  2. 女人多补钙防发胖 七种日常食物含钙高
  3. ARM处理器中CP15协处理器的寄存器1376698090
  4. Ubuntu1804安装pdf阅读软件
  5. esxi虚拟机两个服务器不同网段,esxi主机有双网卡,怎么让主机上运行的两个虚拟机分别通过不同的网卡连接不同的网段?谢谢!...
  6. c语言 英文歌曲大赛,实验部第一届英文歌曲大赛
  7. 解决Xcode模拟器attaching卡死问题
  8. Android绘制小圆点
  9. OceanFax传真服务器连续第二年荣获“中国优秀软件产品奖”
  10. HTML空格类型的区别