// +---------------------------------------------------------------------- namespace app\common\middleware; use app\common\repositories\system\auth\MenuRepository; use app\common\repositories\system\auth\RoleRepository; use app\Request; use Doctrine\Common\Cache\RedisCache; use http\Exception\InvalidArgumentException; use think\facade\Cache; use think\Response; class BlockerMiddleware extends BaseMiddleware { protected $key; public function before(Request $request) { $uid = request()->uid(); $this->key = md5(request()->rule()->getRule() . $uid); if (!$this->setMutex($this->key)) { throw new InvalidArgumentException('请求太过频繁,请稍后再试'); } } public function setMutex(string $key, int $timeout = 10) { $curTime = time(); $readMutexKey = "redis:mutex:{$key}"; $mutexRes = Cache::store('redis')->handler()->setnx($readMutexKey, $curTime + $timeout); if ($mutexRes) { return true; } //就算意外退出,下次进来也会检查key,防止死锁 $time = Cache::store('redis')->handler()->get($readMutexKey); if ($curTime > $time) { Cache::store('redis')->handler()->del($readMutexKey); return Cache::store('redis')->handler()->setnx($readMutexKey, $curTime + $timeout); } return false; } public function after(Response $response) { Cache::store('redis')->handler()->del("redis:mutex:{$this->key}"); // TODO: Implement after() method. } }