تحديد الحد الأقصى لعدد الطلبات لكل مسار في لارافيل

· · 895 كلمة · 5 دقيقة قراءة

الـ rate limit هي طريقة لتحديد الحد الأقصى لعدد الطلبات لموقع الويب في كل دقيقة. هذه الطريقة مهمة جداً لحماية الموقع الإلكتروني ضد الهجمات التي تريد اشباع الخادم الإلكتروني (السيرفر) بكل الطلبات التي يُمكنه الرد عليها، أو محاولة تسجيل الدخول بكل إحتمالات اسم المستخدم وكلمة المرور.

لذلك يحتوى إطار العمل لارافيل على خاصية تحديد الحد الأقصى للطلبات بشكل افتراضي (rate limit) ويُمكننا استخدامها لتحديد الحد الأقصى للطلبات في الدقيقة لكل الطلبات أو بعض الطلبات. يُمكننا أيضاً تحديد الحد الأقصى للطلبات لكل المستخدمين معاً أو لكل مستخدم على حدا.

إنشاء حد أقصى مخصص 🔗

ابدأ بإنشاء حد أقصى للطلبات مخصص لإحتياجات موقعك.

كتابة حد أقصى مخصص للطلبات 🔗

أضف هذا الكود داخل ملف App\Providers\RouteServiceProvider.php داخل الفانكشن configureRateLimiting().

RateLimiter::for('customRateLimiter', function (Request $request) {
    return Limit::perMinute(100);
});

تغيير الحد الأقصى للطلبات للمستخدم وليس الضيف 🔗

إن كنت تريد تغيير الحد الأقصى للطلبات حسب الطالب إن كان مستخدم قام بتسجيل الدخول أم هو زائر لم يقم بتسجيل الدخول بعد.

عدّل الكود السابق ليكون مثل الكود التالي.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(100)->by($request->user()->id)
        : Limit::perMinute(50)->by($request->ip());
});

بعد هذا التغيير ، المستخدم يستطيع عمل مائة طلب في الدقيقة فقط. أما الزائر يستطيع عمل خمسين طلب في الدقيقة فقط. يُمكنك تغيير هذه الأرقام كما تحب.

اعط رد مخصص عند الوصول للحد الأقصى للطلبات 🔗

إن أردت إرسال رد مخصص عندما يصل المستخدم أو الزائر للحد الأقصى من الطلبات، أضف Response لكود الحد الأقصى كما ترى في الكود التالي.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(100)->by($request->user()->id)->response(function () {
            return new Response('Our Server Is Busy, Please Wait!');
        })
        : Limit::perMinute(50)->by($request->ip())->response(function () {
            return new Response('Our Server Is Busy, Please Wait!');
        });
});

يُمكنك تحديد كود حالة الرد بعد الوصول للحد الأقصى.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(100)->by($request->user()->id)->response(function () {
            return new Response('Our Server Is Busy, Please Wait!', 429);
        })
        : Limit::perMinute(50)->by($request->ip())->response(function () {
            return new Response('Our Server Is Busy, Please Wait!', 429);
        });
});

كود حالة الرد 429 يعني الكثير من الطلبات. يُمكنك إستخدام أي كود حالة للرد كما تحب.

للإطلاع على كل أكواد حالة الطلب على شبكة موزيلا للمطورين اضغط هنا .

إن كنت تريد تمرير الـ http headers ، أضفهم بهذا الشكل.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return $request->user()
        ? Limit::perMinute(100)->by($request->user()->id)->response(function (array $headers) {
            return new Response('Our Server Is Busy, Please Wait!', 429, $headers);
        })
        : Limit::perMinute(50)->by($request->ip())->response(function (array $headers) {
            return new Response('Our Server Is Busy, Please Wait!', 429, $headers);
        });
});

تحديد الحد الأقصى للزوار فقط 🔗

إن أردت تحديد الحد الأقصى للطلبات للزوار الغير مسجلين في الموقع فقط ، أضف Limit::none() في حالة أن الطلب من مستخدم مسجل الدخول للموقع كما ترى في الكود التالي.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return $request->user()
        ? Limit::none()
        : Limit::perMinute(50)->by($request->ip())->response(function (array $headers) {
            return new Response('Our Server Is Busy, Please Wait!', 429, $headers);
        });
});

يُمكنك تغيير الحد الأقصى للزوار كما تحب عن طريق تغيير هذه السطور البرمجية من كود الحد الأقصي المخصص للطلبات.

Limit::perMinute(50)->by($request->ip())->response(function (array $headers) {
    return new Response('Our Server Is Busy, Please Wait!', 429, $headers);
});

يُمكنك إزالة الرد المخصص كما ترى في الكود التالي.

Limit::perMinute(50)->by($request->ip());

ويُمكنك أيضاً تغيير الحد الأقصى للطلبات المسموح بها لأي رقم تريده.

تنفيذ الحد الأقصى للطلبات المسموح بها 🔗

كود الحد الأقصى للطلبات المسموح بها الذي قمت بكتابته لن يتم تنفيذه تلقائياً.

تحتاج أنت لتحديد المسارات (routes) التي تريد تطبيق عليها الحد الأقصى للطلبات. يُمكنك تطبيق الحد الأقصى على كل المسارات أو على مسارات محددة.

تطبيق الحد الأقصى للطلبات على كل المسارات 🔗

أضف الحد الأقصى للطلبات المسموح بها لكل مسارات الويب web عن طريق إضافة 'throttle:customRateLimiter' كوسيط middleware في ملف App\Providers\RouteServiceProvider.php كما ترى في الكود التالي.

public function boot()
{
    $this->configureRateLimiting();

    $this->routes(function () {
        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));

        Route::middleware(['web', 'throttle:customRateLimiter'])
            ->group(base_path('routes/web.php'));
    });
}

وهكذا ، كل طلبات http لكل المسارات خاضعة للحد الأقصى الذي حددته.

تطبيق الحد الأقصى للطلبات على مسارات معينة 🔗

أضف middleware('throttle:customRateLimiter') إلى كل المسارات التي تريد تحديد الحد الأقصى لها داخل ملف routes\web.php. إليك بعض الأمثلة لتطبيق الحد الأقصى لمسارات متعددة.

Route::get('/main', function () {
    return view('main');
})->name('main')->middleware(['throttle:customRateLimiter']);

مثال آخر.

Route::group(['middleware' => ['\App\Http\Middleware\CustomCKFinderAuth', 'throttle:customRateLimiter']], function () {
    Route::any('/ckfinder/connector', 'CKSource\CKFinderBridge\Controller\CKFinderController@requestAction')->name('ckfinder_connector');
    Route::any('/ckfinder/browser', 'CKSource\CKFinderBridge\Controller\CKFinderController@browserAction')->name('ckfinder_browser');
});

مثال ثالث.

Route::post('/stores/verify/{id}', [StoreController::class, 'verify'])->middleware(['throttle:customRateLimiter'])->name('stores.verify');

تحديد الحد الأقصى لكل الطلبات من كل المستخدمين للموقع 🔗

في الأكواد السابقة ، كنّا نحدد عدد الطلبات لكل مستخدم في كل دقيقة. لكن إن أردت تحديد الحد الأقصى للطلبات التي يرسلها كافة المستخدمين في الدقيقة لموقعك الإلكتروني، قم فقط بإزالة ->by() من الكود ليكون بالشكل التالي.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return Limit::perMinute(1000)->response(function () {
            return new Response('Our Server Is Busy, Please Wait!');
        });
});

هذا الكود يحدد العدد الأقصى لكل الطلبات التي يستلمها الموقع الإلكتروني في الدقيقة ليكون ١٠٠٠ طلب فقط.

يُمكنك إزالة الرد المخصص من كود الحد الأقصى ليكون كما يلي.

RateLimiter::for('customRateLimiter', function (Request $request) {
    return Limit::perMinute(1000);
});

بعد ذلك أضف الحد الأقصى للطلبات الذي كتبته، إلى كل مسارات الويب web مرةً واحدة عن طريق إضافة 'throttle:customRateLimiter' كوسيط middleware في ملف App\Providers\RouteServiceProvider.php كما ترى في الكود التالي.

public function boot()
{
    $this->configureRateLimiting();

    $this->routes(function () {
        Route::middleware('api')
            ->prefix('api')
            ->group(base_path('routes/api.php'));

        Route::middleware(['web', 'throttle:customRateLimiter'])
            ->group(base_path('routes/web.php'));
    });
}

وهكذا نكون قد جعلنا كل الطلبات إلى كل المسارات في كل الموقع الإلكتروني خاضعة للحد الأقصى للطلبات المسموح بها كما حددنا سابقاً. وهذه الطريقة تساعد كثيراً في حماية الموقع من هجمات DoS و DDoS المشهورين.

أتمني أن تكون استفدت من هذا الشرح.

تابعني على مواقع التواصل الإجتماعي لتعرف كل المقالات والشروحات الجديدة التي أنشرها هنا على مدونة معلومة بإختصار.

التصنيفات: برمجة
مشاركة: