مشخصات مقاله
-
2892
-
0.0
-
11262
-
0
-
0
آموزش HTTP Middleware در لاراول
آموزش HTTP Middleware
فهرست محتوا
- مقدمه
- تعریف و ایجاد Middleware
-
ثبت Middleware
- Middleware های سراسری
- تخصیص Middleware به Route ها
- گروه بندی Middelware ها
- پارامترهای Middleware
- Middlewareهایی که قابل پایان دهی می باشند
مقدمه
HTTP middleware یک سازوکار آسان و بهینه برای فیلتر کردن درخواست های HTTP ارسالی به اپلیکیشن فراهم می آورد. به عنوان مثال، لاراول حاوی یک middleware است که وظیفه ی بررسی اینکه آیا کاربر اپلیکیشن به طور کامل احراز هویت شده است یا خیر را بر عهده دارد. اگر کاربر تصدیق هویت نشده باشد، در آن صورت middleware کاربر را به صفحه ی ثبت ورود (login screen) بازگشت می دهد (redirect). حال اگر کاربر با موفقیت احراز هویت شده باشد، middleware به درخواست اجازه ی ورود به برنامه را می دهد.
البته می توان middleware هایی نوشت که کارهایی علاوه بر احراز هویت کاربر را انجام می دهند. به عنوان نمونه می توان به middleware ای به نام CORS اشاره کرد که وظیفه ی افزودن هدرهای مناسب به تمامی پاسخ هایی را دارد که اپلیکیشن را ترک می کنند. Middleware ثبت وقایع ممکن است تمامی درخواست های ارسالی به اپلیکشین را ثبت کند.
تعداد زیادی middleware در فریم ورک لاراول تعبیه شده که از جمله ی آن می توان به middleware تعمیر و نگهداشت (maintenance)، احراز هویت (authentication)، جلوگیری از حمله ی CSRF (CSRF protection) اشاره کرد. تمامی middleware های نام برده در پوشه یapp/Http/Middleware جای دارند.
تعریف و ایجاد Middleware
به منظور ایجاد یک middleware جدید می توان از دستور آرتیزانmake:middleware بهره گرفت:
php artisan make:middleware AgeMiddleware
این دستور یک کلاس AgeMiddleware جدید در پوشه ی app/Http/Middleware قرار می دهد. در middleware مزبور ما تنها دسترسی بهroute را زمانی امکان پذیر می کنیم که age فراهم شده بزرگتر از مقدار 200 باشد. در غیر این صورت، کاربران را به آدرس "home" ارجاع می دهیم (redirect می کنیم).
<?php
namespace App\Http\Middleware;
use Closure;
class AgeMiddleware
{
/**
* Run the request filter.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->input('age') <= 200) {
return redirect('home');
}
return $next($request);
}
}
همان طور که مشاهده می شود، در صورتی که مقدار ورودی age کمتر یا مساوی 200 باشد، middleware یک HTTP redirect به سرویس گیرنده (کلاینت) برمی گرداند، در غیر این صورت درخواست به داخل برنامه راه یافته و کاربر می تواند وارد بخش مورد نظر شود. برای اجازه ی ورود درخواست به برنامه (برای اجازه ی ورود یا "pass" به middleware)، کافی است تابع $next که یک تابع callback است را همراه با آرگومان $requestفراخوانی نمایید.
بد نیست به middleware به چشم یک سری لایه نگاه کنید که درخواست های HTTP می بایست برای دسترسی به برنامه پشت سر بگذارد. هر لایه می تواند درخواست را بررسی کرده و در صورت لزوم آن را به طور کلی کاملا رد کند.
Before / After Middleware (اجرای middleware قبل و بعد از درخواست)
اینکه آیا یک Middleware بایستی پیش یا پس از یک درخواست اجرا شود، در واقع به خود آن middleware بستگی دارد. به عنوان مثال،middleware ذکر شده در زیر پیش از اینکه درخواست توسط برنامه مدیریت شود، عملیات خاصی را انجام می دهد:
<?php
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
اما middleware موجود در نمونه ی زیر، عملیات مورد نظر را پس از مدیریت درخواست توسط برنامه اجرا می کند:
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}
ثبت Middleware
Middleware های سراسری
اگر می خواهید middleware در طول هر درخواست ارسالی به برنامه اجرا شود، کافی است کلاس middleware را در پراپرتی $middleware از کلاس app/Http/Kernel.php لیست کنید.
تخصیص Middleware به Route ها
اگر می خواهید middleware به route های خاصی اختصاص داده شود، بایستی ابتدا یک کلید مختصر در فایل app/Http/Kernel.php بهmiddleware تخصیص دهید. به صورت پیش فرض، property (خاصیت)$routeMiddleware از این کلاس دربردارنده ی middleware های درون ساخته ی می باشد. برای اضافه کردن middleware اختصاصی خود، کافی است آن را به این لیست الحاق کرده و سپس یک کلید به دلخواه خود به آن تخصیص دهید.
// Within App\Http\Kernel Class... protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, ];
پس از اینکه middleware را در هسته (kernel) HTTP تعریف کردید، آن زمان می توانید کلید middleware را در آرایه ی option هایroute بکار ببرید:
Route::get('admin/profile', ['middleware' => 'auth', function () {
//
}]);
از یک آرایه برای تخصیص چندین middleware به route استفاده می شود:
Route::get('/', ['middleware' => ['first', 'second'], function () {
//
}]);
بجای استفاده از یک آرایه می توانید متد middleware را به انتهای تعریف route متصل کنید:
Route::get('/', function () {
//
})->middleware(['first', 'second']);
به هنگام تخصیص middleware، همچنین می توانید اسم کامل کلاس را پاس دهید:
use App\Http\Middleware\FooMiddleware;
Route::get('admin/profile', ['middleware' => FooMiddleware::class, function () {
//
}]);
گروه بندی Middleware ها
گاهی لازم است چندین middleware را تحت یک کلید یکسان گروه بندی کرده تا تخصیص آن ها به route ها آسان تر گردد (به چندینmiddleware کلید یکسان تخصیص دهید). برای این منظور کافی است از خاصیت $middlewareGroups هسته ی HTTP استفاده کنید.
Web و api دو middleware گروه بندی شده و خارج از سازمان (علاوه بر middleware های پیش فرض) هستند که حاوی یک middlewareمشترک می باشند. می توانید آن را به web UI و API route ها اعمال نمایید.
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];
Middleware های گروه بندی شده را می توان با همان ساختار نگارشی که برای تخصیص middleware های منفرد استفاده می کنید، به route ها وaction های کنترلر انتساب دهید. بازهم یادآور می شویم که middleware های گروه بندی شده صرفا تخصیص همزمان چندین middlewareمتعدد به یک route را آسان تر می سازند.
Route::group(['middleware' => ['web']], function () {
//
});
لازه به ذکر است که middleware گروه بندی شده ی web به صورت خودکار توسط RouteServiceProvider به فایل routes.php اعمال می شود.
پارامترهای Middleware
Middleware همچنین قادر است پارامترهای اختصاصی اضافی بر سازمان دریافت کند. به عنوان مثال، اگر اپلیکیشن شما، پیش از انجام عملیات خاصی، بایستی بررسی کرده و اطمینان حاصل کند که user احراز هویت شده دارای نقش کاربری معین است، در آن صورت شما می توانید یکRoleMiddleware ایجاد کرده و اسم نقش کاربری مربوطه را به عنوان آرگومان به آن پاس دهید.
پارامترهای اضافی بر سازمان بعد از آرگومان $next به middleware پاس داده می شوند:
<?php
namespace App\Http\Middleware;
use Closure;
class RoleMiddleware
{
/**
* Run the request filter.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string $role
* @return mixed
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
پارامترهای middleware را می توان به هنگام تعریف route، با جدا کردن اسم middleware و پارامترها به وسیله ی " : "، مشخص کرد. چندین پارامتر را می توان توسط ویرگول از هم تفکیک کرد:
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
//
}]);
Middleware های قابل پایان دهی
گاهی یک middleware می بایست کار یا عملیات خاصی را بعد از این که پاسخ HTTP به مرورگر ارسال شد، انجام دهد. برای مثال میان افزار "session"، از middleware های پیش فرض لاراول، داده های session را پس از اینکه پاسخ به مرورگر فرستاده شد، در حافظه ذخیره می کند. برای این منظور لازم است middleware را با افزودن متد terminate به آن، قابل پایان دهی یا به اصطلاح " terminable " تعریف نمایید.
<?php
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Store the session data...
}
}
متد terminate بایستی هم درخواست و هم پاسخ را دریافت کند. بعد از اینکه یک middleware با قابلیت پایان یابی تعریف کردید، بایستی آن را به لیست middleware های سراسری در هسته ی HTTP خود اضافه کنید. اگر مایلید در زمان فراخوانی متدهای terminate و handle، یک نمونهmiddleware یکسان را بکار ببرید، در آن صورت باید middleware را در container به وسیله ی متد singleton متصل (bind) کنید.