میان افزار
معرفی
Middleware مکانیزم مناسبی را برای بازرسی و فیلتر کردن درخواستهای HTTP که وارد برنامه شما میشوند فراهم میکند. به عنوان مثال، لاراول شامل یک میان افزار است که تأیید می کند کاربر برنامه شما احراز هویت شده است. اگر کاربر احراز هویت نشده باشد، میان افزار کاربر را به صفحه ورود به سیستم برنامه شما هدایت می کند. با این حال، اگر کاربر احراز هویت شود، میانافزار به درخواست اجازه میدهد تا در برنامه ادامه یابد.
میانافزار اضافی را میتوان برای انجام کارهای مختلف علاوه بر احراز هویت نوشت. به عنوان مثال، یک میان افزار لاگ ممکن است تمام درخواست های دریافتی را به برنامه شما ثبت کند. انواع میانافزار در لاراول گنجانده شده است، از جمله میانافزار برای احراز هویت و حفاظت CSRF. با این حال، همه میان افزارهای تعریف شده توسط کاربر معمولاً در
app/Http/Middleware
فهرست برنامه شما قرار دارند.
تعریف میان افزار
برای ایجاد یک میان افزار جدید، از
make:middleware
دستور Artisan استفاده کنید:
php artisan make:middleware EnsureTokenIsValid
EnsureTokenIsValid
این دستور یک کلاس جدید را در دایرکتوری شما
قرار می دهد
app/Http/Middleware
. در این میان افزار، تنها در صورتی اجازه دسترسی به مسیر را می دهیم که
token
ورودی ارائه شده با مقدار مشخصی مطابقت داشته باشد. در غیر این صورت، کاربران را به URI هدایت خواهیم کرد
home
:
<?php namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class EnsureTokenIsValid{ /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { if ($request->input('token') !== 'my-secret-token') { return redirect('home'); } return $next($request); }}
همانطور که می بینید، اگر داده شده با
token
توکن مخفی ما مطابقت نداشته باشد، میان افزار یک تغییر مسیر HTTP را به مشتری برمی گرداند. در غیر این صورت، درخواست بیشتر به برنامه ارسال می شود. برای ارسال درخواست عمیق تر به برنامه (اجازه دادن به میان افزار برای "عبور")، باید
$next
با استفاده از
$request
.
بهتر است میانافزار را بهعنوان یک سری از درخواستهای HTTP «لایهها» تصور کنید که قبل از ورود به برنامه شما باید از آن عبور کنند. هر لایه می تواند درخواست را بررسی کند و حتی آن را به طور کامل رد کند.
همه میانافزارها از طریق کانتینر سرویس حل میشوند ، بنابراین میتوانید وابستگیهایی را که در سازنده میانافزار نیاز دارید تایپ کنید.
میان افزار و پاسخ ها
البته، یک میانافزار میتواند وظایفی را قبل یا بعد از ارسال درخواست به عمق برنامه انجام دهد. به عنوان مثال، میان افزار زیر برخی از وظایف را قبل از رسیدگی به درخواست توسط برنامه انجام می دهد:
<?php namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class BeforeMiddleware{ public function handle(Request $request, Closure $next): Response { // Perform action return $next($request); }}
با این حال، این میان افزار پس از رسیدگی به درخواست توسط برنامه، وظیفه خود را انجام می دهد:
<?php namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class AfterMiddleware{ public function handle(Request $request, Closure $next): Response { $response = $next($request); // Perform action return $response; }}
ثبت نرم افزار میانی
میان افزار جهانی
اگر می خواهید یک میان افزار در طول هر درخواست HTTP برای برنامه شما اجرا شود، می توانید آن را به پشته میان افزار جهانی در
bootstrap/app.php
فایل برنامه خود اضافه کنید:
use App\Http\Middleware\EnsureTokenIsValid; ->withMiddleware(function (Middleware $middleware) { $middleware->append(EnsureTokenIsValid::class);})
شی
$middleware
ارائه شده به
withMiddleware
بسته شدن نمونه ای از
Illuminate\Foundation\Configuration\Middleware
و مسئول مدیریت میان افزار اختصاص داده شده به مسیرهای برنامه شما است. این
append
روش میان افزار را به انتهای لیست میان افزارهای جهانی اضافه می کند. اگر می خواهید یک میان افزار به ابتدای لیست اضافه کنید، باید از
prepend
روش استفاده کنید.
مدیریت دستی میان افزار جهانی پیش فرض لاراول
اگر میخواهید پشته میانافزار جهانی لاراول را به صورت دستی مدیریت کنید، میتوانید پشته میانافزار جهانی لاراول پیشفرض را به روش ارائه دهید
use
. سپس، میتوانید پشته میانافزار پیشفرض را در صورت لزوم تنظیم کنید:
->withMiddleware(function (Middleware $middleware) { $middleware->use([ // \Illuminate\Http\Middleware\TrustHosts::class, \Illuminate\Http\Middleware\TrustProxies::class, \Illuminate\Http\Middleware\HandleCors::class, \Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Http\Middleware\ValidatePostSize::class, \Illuminate\Foundation\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, ]);})
اختصاص نرم افزار میانی به مسیرها
اگر میخواهید میانافزار را به مسیرهای خاصی اختصاص دهید، میتوانید
middleware
هنگام تعریف مسیر از روش استفاده کنید:
use App\Http\Middleware\EnsureTokenIsValid; Route::get('/profile', function () { // ...})->middleware(EnsureTokenIsValid::class);
میتوانید با ارسال آرایهای از نامهای میانافزار به
middleware
روش، چند میانافزار را به مسیر اختصاص دهید:
Route::get('/', function () { // ...})->middleware([First::class, Second::class]);
به استثنای میان افزار
هنگامی که میانافزار را به گروهی از مسیرها اختصاص میدهید، ممکن است گاهی لازم باشد از اعمال میانافزار به یک مسیر جداگانه در گروه جلوگیری کنید. شما می توانید این کار را با استفاده از
withoutMiddleware
روش زیر انجام دهید:
use App\Http\Middleware\EnsureTokenIsValid; Route::middleware([EnsureTokenIsValid::class])->group(function () { Route::get('/', function () { // ... }); Route::get('/profile', function () { // ... })->withoutMiddleware([EnsureTokenIsValid::class]);});
همچنین میتوانید مجموعه معینی از میانافزار را از کل گروهی از تعاریف مسیر حذف کنید:
use App\Http\Middleware\EnsureTokenIsValid; Route::withoutMiddleware([EnsureTokenIsValid::class])->group(function () { Route::get('/profile', function () { // ... });});
این روش فقط می تواند میان افزار مسیر را حذف کند و برای
میان افزار جهانی
withoutMiddleware
اعمال نمی شود
.
گروه های میان افزار
گاهی اوقات ممکن است بخواهید چندین میان افزار را زیر یک کلید گروه بندی کنید تا تخصیص آنها به مسیرها آسان تر شود. می توانید این کار را با استفاده از
appendToGroup
روش موجود در فایل برنامه خود انجام دهید
bootstrap/app.php
:
use App\Http\Middleware\First;use App\Http\Middleware\Second; ->withMiddleware(function (Middleware $middleware) { $middleware->appendToGroup('group-name', [ First::class, Second::class, ]); $middleware->prependToGroup('group-name', [ First::class, Second::class, ]);})
ممکن است گروههای میانافزار به مسیرها و کنشهای کنترلکننده با استفاده از نحو مشابه میانافزار منفرد اختصاص داده شوند:
Route::get('/', function () { // ...})->middleware('group-name'); Route::middleware(['group-name'])->group(function () { // ...});
گروه های میان افزار پیش فرض لاراول
لاراول شامل گروههای از پیش تعریفشده
web
و
api
میانافزاری است که حاوی میانافزار رایجی هستند که ممکن است بخواهید در مسیرهای وب و API خود اعمال کنید. به یاد داشته باشید، لاراول به طور خودکار این گروه های میان افزاری را در فایل ها
routes/web.php
و فایل های
مربوطه اعمال می کند
routes/api.php
:
گروه
web
میان افزار
|
---|
Illuminate\Cookie\Middleware\EncryptCookies |
Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse |
Illuminate\Session\Middleware\StartSession |
Illuminate\View\Middleware\ShareErrorsFromSession |
Illuminate\Foundation\Http\Middleware\ValidateCsrfToken |
Illuminate\Routing\Middleware\SubstituteBindings |
گروه
api
میان افزار
|
---|
Illuminate\Routing\Middleware\SubstituteBindings |
اگر میخواهید میانافزار را به این گروهها اضافه یا اضافه کنید، میتوانید از روشهای
web
و
api
در فایل برنامه خود استفاده کنید
bootstrap/app.php
. و روش
web
ها
api
جایگزین مناسبی برای
appendToGroup
روش هستند:
use App\Http\Middleware\EnsureTokenIsValid;use App\Http\Middleware\EnsureUserIsSubscribed; ->withMiddleware(function (Middleware $middleware) { $middleware->web(append: [ EnsureUserIsSubscribed::class, ]); $middleware->api(prepend: [ EnsureTokenIsValid::class, ]);})
حتی میتوانید یکی از ورودیهای گروه میانافزار پیشفرض لاراول را با یک میانافزار سفارشی خود جایگزین کنید:
use App\Http\Middleware\StartCustomSession;use Illuminate\Session\Middleware\StartSession; $middleware->web(replace: [ StartSession::class => StartCustomSession::class,]);
یا، می توانید یک میان افزار را به طور کامل حذف کنید:
$middleware->web(remove: [ StartSession::class,]);
مدیریت دستی گروه های میان افزار پیش فرض لاراول
اگر میخواهید به صورت دستی تمام میانافزارها را در گروههای پیشفرض
web
و
api
میانافزار لاراول مدیریت کنید، میتوانید گروهها را به طور کامل دوباره تعریف کنید. مثال زیر گروههای میانافزار
web
و
api
میانافزار را با میانافزار پیشفرضشان تعریف میکند و به شما امکان میدهد در صورت لزوم آنها را سفارشی کنید:
->withMiddleware(function (Middleware $middleware) { $middleware->group('web', [ \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, // \Illuminate\Session\Middleware\AuthenticateSession::class, ]); $middleware->group('api', [ // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ]);})
به طور پیشفرض، گروههای میانافزار
web
و میانافزار بهطور خودکار بر روی فایلهای مربوطه و فایلهایapi
برنامه شما اعمال میشوند .routes/web.php
routes/api.php
bootstrap/app.php
نام مستعار میان افزار
شما می توانید نام مستعار را به میان افزار در فایل برنامه خود اختصاص دهید
bootstrap/app.php
. نام مستعار میانافزار به شما امکان میدهد یک نام مستعار کوتاه برای یک کلاس میانافزار معین تعریف کنید، که میتواند به ویژه برای میانافزار با نامهای کلاس طولانی مفید باشد:
use App\Http\Middleware\EnsureUserIsSubscribed; ->withMiddleware(function (Middleware $middleware) { $middleware->alias([ 'subscribed' => EnsureUserIsSubscribed::class ]);})
هنگامی که نام مستعار میانافزار در فایل برنامه شما تعریف شد
bootstrap/app.php
، میتوانید هنگام اختصاص دادن میانافزار به مسیرها از نام مستعار استفاده کنید:
Route::get('/profile', function () { // ...})->middleware('subscribed');
برای راحتی، برخی از میان افزارهای داخلی لاراول به طور پیش فرض نام مستعار دارند. به عنوان مثال،
auth
میان افزار نام مستعار
Illuminate\Auth\Middleware\Authenticate
میان افزار است. در زیر لیستی از نام مستعار میان افزار پیش فرض آمده است:
نام مستعار | میان افزار |
---|---|
auth |
Illuminate\Auth\Middleware\Authenticate |
auth.basic |
Illuminate\Auth\Middleware\AuthenticateWithBasicAuth |
auth.session |
Illuminate\Session\Middleware\AuthenticateSession |
cache.headers |
Illuminate\Http\Middleware\SetCacheHeaders |
can |
Illuminate\Auth\Middleware\Authorize |
guest |
Illuminate\Auth\Middleware\RedirectIfAuthenticated |
password.confirm |
Illuminate\Auth\Middleware\RequirePassword |
precognitive |
Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests |
signed |
Illuminate\Routing\Middleware\ValidateSignature |
subscribed |
\Spark\Http\Middleware\VerifyBillableIsSubscribed |
throttle |
Illuminate\Routing\Middleware\ThrottleRequests
یا
Illuminate\Routing\Middleware\ThrottleRequestsWithRedis
|
verified |
Illuminate\Auth\Middleware\EnsureEmailIsVerified |
مرتب سازی میان افزارها
به ندرت، ممکن است نیاز داشته باشید که میان افزار خود را با یک ترتیب خاص اجرا کنید، اما زمانی که به مسیر اختصاص داده می شود، کنترلی بر ترتیب آنها نداشته باشید. در این شرایط، می توانید اولویت میان افزار خود را با استفاده از
priority
روش موجود در فایل برنامه خود مشخص کنید
bootstrap/app.php
:
->withMiddleware(function (Middleware $middleware) { $middleware->priority([ \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class, \Illuminate\Cookie\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, \Illuminate\Routing\Middleware\ThrottleRequests::class, \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class, \Illuminate\Auth\Middleware\Authorize::class, ]);})
پارامترهای میان افزار
میان افزار همچنین می تواند پارامترهای اضافی را دریافت کند. به عنوان مثال، اگر برنامه شما باید قبل از انجام یک عمل مشخص، تأیید کند که کاربر تأیید شده دارای یک "نقش" است، می توانید یک
EnsureUserHasRole
میان افزار ایجاد کنید که یک نام نقش را به عنوان یک آرگومان اضافی دریافت کند.
پارامترهای میانافزار اضافی پس از آرگومان به میانافزار ارسال میشوند
$next
:
<?php namespace App\Http\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class EnsureUserHasRole{ /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next, string $role): Response { if (! $request->user()->hasRole($role)) { // Redirect... } return $next($request); } }
پارامترهای میانافزار ممکن است هنگام تعریف مسیر با جدا کردن نام میانافزار و پارامترها با علامت زیر مشخص شوند
:
:
Route::put('/post/{id}', function (string $id) { // ...})->middleware('role:editor');
ممکن است چندین پارامتر با کاما مشخص شوند:
Route::put('/post/{id}', function (string $id) { // ...})->middleware('role:editor,publisher');
میان افزار پایان پذیر
گاهی اوقات ممکن است پس از ارسال پاسخ HTTP به مرورگر، یک میان افزار نیاز به انجام برخی کارها داشته باشد. اگر روشی را در میان افزار خود تعریف کنید
terminate
و سرور وب شما از FastCGI استفاده می کند،
terminate
پس از ارسال پاسخ به مرورگر، روش به طور خودکار فراخوانی می شود:
<?php namespace Illuminate\Session\Middleware; use Closure;use Illuminate\Http\Request;use Symfony\Component\HttpFoundation\Response; class TerminatingMiddleware{ /** * Handle an incoming request. * * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next */ public function handle(Request $request, Closure $next): Response { return $next($request); } /** * Handle tasks after the response has been sent to the browser. */ public function terminate(Request $request, Response $response): void { // ... }}
متد
terminate
باید هم درخواست و هم پاسخ را دریافت کند. هنگامی که یک میان افزار پایان پذیر تعریف کردید، باید آن را به لیست مسیرها یا میان افزار جهانی در
bootstrap/app.php
فایل برنامه خود اضافه کنید.
هنگام فراخوانی
terminate
متد در میانافزار، لاراول یک نمونه جدید از میانافزار را از
کانتینر سرویس
حل میکند . اگر میخواهید هنگام فراخوانی متدهای
handle
و
از همان نمونه میانافزار استفاده کنید
terminate
، میانافزار را با استفاده از متد Container در Container ثبت کنید
singleton
. معمولاً این باید در
register
روش شما
انجام شود
AppServiceProvider
:
use App\Http\Middleware\TerminatingMiddleware; /** * Register any application services. */public function register(): void{ $this->app->singleton(TerminatingMiddleware::class);}