Laravel5.0 限制请求频率中间件
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Cache;
use App\Libs\Xres;
class ThrottleRequests {
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
$unique = $request->getClientIp() . $request->getRequestUri();
if (Cache::has('ip_list')) {
$ip_list = Cache::get('ip_list');
} else {
$ip_list = array();
}
$index = array_search($unique, array_column($ip_list, 'ip'));
if (false === $index) {
array_push($ip_list, ['ip' => $unique, 'time' => $this->time()]);
Cache::put('ip_list', $ip_list, 1440);
} else {
$gap = $this->time() - $ip_list[$index]['time'];
$ip_list[$index]['time'] = $this->time();
Cache::put('ip_list', $ip_list, 1440);
if ($gap < 1000) {
return Xres::error("请求频率过快", 200);
}
}
return $next($request);
}
private function time(){
return (int)(microtime(true)*1000);
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu
为什么第二次的有效期改为1
Cache::put('ip_list', $ip_list, 1);@lovecn 对,不应该1分钟。应该改成1440.不过时间我觉得应该没有太大问题。就算是一分钟也不影响功能。因为主要是防止大量短时间的频繁请求。所以一分钟也没有问题的。不过最好是统一
直接用 redis 做比较适合吧
这个把 ip_list 缓存,再取出来,查询数组。当 缓存的数据多了,array_search 性能不好吧
如果是一个外网IP,内部有许多的内网IP,这些人同时访问,体验不就很差?
而且这个功能都有哪些使用场景呢?
一个是局域网问题 一个是如果用户量大了 $ip_list是一个瓶颈问题
谢谢各位留言,这个中间件是防止被大量循环请求。这个功能在laravel5.2是自带的。至于局域网同一ip问题,将间隔时间尽量减少吧。100毫秒应该没有问题的。我是ip加接口来判断的。一个局域网多个用户同时极短时间内访问同一个接口是很少有的。至于瓶颈问题,我没有测试过。
应用场景。就是你网站被短时间大量访问同一接口而崩溃。你应该就需要了
需要就可以拿去用,不需要就随便看看就好了。