首頁>技術>

每天進步一點點...

新建的網站,如何限制別人惡意攻擊、頻繁請求介面,導致資料庫崩潰?我們可以使用Redis對請求的IP做一個簡單的限制。

一、設計思路

1、Redis中使用有序set表存放黑名單列表、頻繁請求列表。

2、使用者訪問,設定一個鎖,數值為1,過期時間10秒。

3、使用者每次請求介面1次,鎖的數值加1。在10秒內介面訪問次數超過20次,則把該使用者IP或uid新增到頻繁請求列表中,score的值為當前時間,資料庫表頻繁請求次加1。

4、若頻繁請求次數超過設定次數,則新增到redis黑名單列表中。

二、前期準備

1、在app\http\common中建立RedisKey.php

<?phpnamespace App\Http\Common;class RedisKey{    public static $USER_BLACK_LIST = "user:black:list";//黑名單列表    public static $USER_FREQUENT_REQUEST_LIST = "user:frequent:request:list";//頻繁請求列表    public static $USER_FREQUENT_REQUEST_LOCK = "user:frequent:request:lock";//鎖}

2、建立資料庫表

user表

3、使用命令建立CheckRequest.php路由中介軟體

php artisan make:middleware CheckRequest
三、實現程式碼
<?phpnamespace App\Http\Middleware;use App\Http\Common\Code;use App\Http\Common\RedisKey;use App\Models\FrontUser;use Closure;use Illuminate\Http\Request;use Illuminate\Support\Facades\Redis;class CheckRequest{    /**     * Handle an incoming request.     *     * @param Request $request     * @param Closure $next     * @return mixed     */    public function handle($request, Closure $next)    {        $ip = request()->ip();        //檢視redis黑名單中是否存在該IP        $isBlack = Redis::zscore(RedisKey::$USER_BLACK_LIST, $ip);        if ($isBlack) {            return ["code" => Code::$USER_BLACK, "msg" => "由於您近期異常請求過於頻繁,已限制訪問。如需取消限制,請聯絡管理員:郵箱[email protected]!"];        }        $user = new FrontUser();        $isUser = $user->where(["ip" => $ip])->first();        //資料庫中已設定為黑名單或頻繁請求數大於等於10        if ($isUser) {        //檢視資料庫表中頻繁請求次數是否超過10次,是就把該使用者列入黑名單並修改相關欄位            if ($isUser->black_list === 1 || $isUser->frequent_num >= 10) {                $isUser->black_list = 1;                $isUser->save();                Redis::zadd(RedisKey::$USER_BLACK_LIST, 1, $isUser->ip);                return ["code" => Code::$USER_BLACK, "msg" => "由於您近期異常請求過於頻繁,已限制訪問。如需取消限制,請聯絡管理員:郵箱[email protected]!"];            }        }        $time = 5;//鎖過期時間        $limit = 20;//5秒內請求次數,超過就觸發防刷機制        $lock_time = 60;//每次防刷的鎖60秒        //redis頻繁請求列表        $start_time = Redis::zscore(RedisKey::$USER_FREQUENT_REQUEST_LIST, $ip);        //如果redis頻繁請求列表中存在該使用者IP,且間隔當前時間少於60秒        if (time() - $start_time < $lock_time) {            //返回剩餘時間            return response(["code" => Code::$USER_FREQUENT, "msg" => "頻繁請求!", "data" => $lock_time - (time() - $start_time)]);        }        $frequentLock = RedisKey::$USER_FREQUENT_REQUEST_LOCK . ":" . $ip;        $isFrequent = Redis::get($frequentLock);        if (!$isFrequent) {            Redis::setex($frequentLock, $time, 1); //設定鎖            return $next($request);        }        Redis::incr($frequentLock);//鎖過期時間類數值自增        //設定時間內請求次數大於設定次數,觸發防刷機制        if ($isFrequent > $limit) {            Redis::zadd(RedisKey::$USER_FREQUENT_REQUEST_LIST, time(), $ip);            Redis::expire(RedisKey::$USER_FREQUENT_REQUEST_LIST, 60 * 5);            $isUser->increment("frequent_num");            $isUser->save();        }        return $next($request);    }}
四、實現效果

效果圖

12
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • loadrunner學習-關聯是什麼?該如何做?