* @date 2020-01-31 10:39:38 */ declare(strict_types=1); namespace App\Repositories; use App\Constants\CreatorConstant; use App\Model\BannedIpModel; use App\Model\UserModel; use Carbon\Carbon; use Hyperf\Redis\Redis; use KZ2\Repositories\Model\Repository; use Psr\SimpleCache\CacheInterface; class BannedIpRepository extends Repository { public function model() { return BannedIpModel::class; } /** * 是否禁用IP * @param $ip * @return bool */ public function isBanned($ip) { $ip = trim($ip); return BannedIpModel::query()->where(['ip' => $ip])->exists(); } /** * 禁止1个IP. * @param $ip * @return \Hyperf\Database\Model\Builder|\Hyperf\Database\Model\Model */ public function doBan($ip) { $ip = trim($ip); return BannedIpModel::query()->create(['ip' => $ip]); } /** * 删除一个IP * @param $ip * @return false|int|mixed */ public function deleteOne($ip) { $ip = trim($ip); return BannedIpModel::query()->where(['ip' => $ip])->take(1)->delete(); } /** * 检查黑名单规则. * @param $ip * @param array $params * @return bool */ public function checkBlackRule($ip, $params = []) { $ip = trim($ip); $cacheRepo = make(Redis::class); $cacheKey = env('SERVER_CACHE_PREFIX', '') . 'user_ip_check'; $ipValue = $cacheRepo->hget($cacheKey, $ip); $nowDateObj = Carbon::now(); $isNeedCheck = false; // 默认不检查. if (!empty($ipValue)) { // 有值,还需要查看值是否是是当天日期. $ipNextCheckDateObj = Carbon::parse($ipValue); if ($ipNextCheckDateObj < $nowDateObj) { // 下次检查时间小于当前时间,则需要执行检查. $isNeedCheck = true; } } else { $isNeedCheck = true; } if ($isNeedCheck) { $redNum = 25; // 相同IP,当日注册红线数量. $startDateObj = Carbon::now()->startOfDay(); $endDateObj = Carbon::now()->endOfDay(); // $startDateObj = Carbon::now()->subMinutes(5); // $endDateObj = Carbon::now(); // 统计今天时间段内,相同IP,注册用户数量 $countIpUsers = UserModel::query()->where(['ip' => $ip]) ->whereBetween('created_at', [$startDateObj, $endDateObj]) ->orderByDesc('id') ->count('id'); if ($countIpUsers >= $redNum) { // 超过红线,执行禁止IP操作,下次一同一个IP无法注册. if (!$this->isBanned($ip)) { $this->doBan($ip); } } $nextCheckDateObj = Carbon::now()->addMinutes(5); $nextCheckDate = $nextCheckDateObj->toDateTimeString(); $cacheRepo->hset($cacheKey, $ip, $nextCheckDate); // 设置下次检查时间. } return true; } /** * 清空IP. */ public function clearAllIp() { BannedIpModel::query()->truncate(); } }