Вступление

Промежуточное программное обеспечение предоставляет удобный механизм фильтрации HTTP-запросов, поступающих в ваше приложение. Например, Laravel включает промежуточное программное обеспечение, которое проверяет подлинность пользователя вашего приложения. Если пользователь не аутентифицирован, промежуточное программное обеспечение перенаправит пользователя на экран входа в систему. Однако, если пользователь аутентифицирован, промежуточное программное обеспечение позволит запросу продолжить работу в приложении.

Дополнительное промежуточное программное обеспечение может быть написано для выполнения различных задач, помимо аутентификации. Промежуточное программное обеспечение CORS может отвечать за добавление правильных заголовков ко всем ответам, покидающим ваше приложение. Промежуточное программное обеспечение может регистрировать все входящие запросы к вашему приложению.

В инфраструктуру Laravel включено несколько промежуточных программ, в том числе промежуточное ПО для аутентификации и защиты CSRF. Все эти промежуточные программы находятся в каталоге.app/Http/Middleware

 

Определение промежуточного программного обеспечения

Чтобы создать новое промежуточное программное обеспечение, используйте команду Artisan:make:middleware

php artisan make:middleware CheckAge

Эта команда поместит новый CheckAgeкласс в ваш каталог. В этом промежуточном программном обеспечении мы будем разрешать доступ к маршруту только в том случае, если он превышает 200. В противном случае мы перенаправим пользователей обратно на URI:app/Http/Middlewareagehome

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAge
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        if ($request->age <= 200) {
            return redirect('home');
        }

        return $next($request);
    }
}

Как вы можете видеть, если заданное значение ageменьше или равно 200, промежуточное программное обеспечение вернет HTTP-перенаправление клиенту; в противном случае запрос будет передан дальше в приложение. Чтобы передать запрос глубже в приложение (позволяя промежуточному программному обеспечению «пройти»), вызовите $nextфункцию обратного вызова с помощью $request.

Лучше всего представить промежуточное ПО, поскольку ряд «слоев» HTTP-запросов должен пройти до того, как они попадут в ваше приложение. Каждый уровень может изучить запрос и даже полностью отклонить его.

Все промежуточное программное обеспечение разрешается с помощью сервисного контейнера , поэтому вы можете указывать любые зависимости, которые вам нужны, в конструкторе промежуточного программного обеспечения.

До и после промежуточного программного обеспечения

Работает ли промежуточное программное обеспечение до или после запроса, зависит от самого промежуточного программного обеспечения. Например, следующее промежуточное программное обеспечение будет выполнять некоторую задачу перед обработкой запроса приложением:

<?php

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
    public function handle($request, Closure $next)
    {
        // Perform action

        return $next($request);
    }
}

Тем не менее, это промежуточное программное обеспечение будет выполнять свою задачу после обработки запроса приложением:

<?php

namespace App\Http\Middleware;

use Closure;

class AfterMiddleware
{
    public function handle($request, Closure $next)
    {
        $response = $next($request);

        // Perform action

        return $response;
    }
}

 

Регистрация Middleware

Global Middleware

Если вы хотите, чтобы промежуточное программное обеспечение запускалось во время каждого HTTP-запроса к вашему приложению, $middlewareукажите класс промежуточного программного обеспечения в свойстве вашего класса.app/Http/Kernel.php

 

Назначение промежуточного программного обеспечения для маршрутов

Если вы хотите назначить промежуточное программное обеспечение для определенных маршрутов, вы должны сначала назначить промежуточному программному обеспечению ключ в вашем файле. По умолчанию свойство этого класса содержит записи для промежуточного программного обеспечения, включенного в Laravel. Чтобы добавить свой собственный, добавьте его в этот список и назначьте ключ по вашему выбору:app/Http/Kernel.php$routeMiddleware

// Within App\Http\Kernel Class...

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
    'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
    'can' => \Illuminate\Auth\Middleware\Authorize::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];

После того, как промежуточное ПО было определено в ядре HTTP, вы можете использовать middlewareметод для назначения промежуточного ПО для маршрута:

Route::get('admin/profile', function () {
    //
})->middleware('auth');

Вы также можете назначить несколько промежуточных программ для маршрута:

Route::get('/', function () {
    //
})->middleware('first', 'second');

При назначении промежуточного программного обеспечения вы также можете передать полное имя класса:

use App\Http\Middleware\CheckAge;

Route::get('admin/profile', function () {
    //
})->middleware(CheckAge::class);

 

Группы промежуточного программного обеспечения

Иногда вам может потребоваться сгруппировать несколько промежуточных программ под одним ключом, чтобы их было проще назначать маршрутам. Вы можете сделать это, используя $middlewareGroupsсвойство вашего HTTP-ядра.

Из коробки поставляется Laravel webи apiгруппы промежуточного программного обеспечения, которые содержат общее промежуточное программное обеспечение, которое вы можете применить к своим веб-интерфейсам и маршрутам API:

/**
 * 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,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
    ],

    'api' => [
        'throttle:60,1',
        'auth:api',
    ],
];

Группы промежуточного программного обеспечения могут быть назначены маршрутам и действиям контроллера с использованием того же синтаксиса, что и отдельное промежуточное программное обеспечение. Опять же, группы промежуточного ПО делают более удобным назначение сразу нескольких промежуточных программ для маршрута:

Route::get('/', function () {
    //
})->middleware('web');

Route::group(['middleware' => ['web']], function () {
    //
});

Из коробки webгруппа промежуточного программного обеспечения автоматически применяется к вашему файлу .routes/web.phpRouteServiceProvider

Сортировка Middleware

В редких случаях вам может понадобиться ваше промежуточное программное обеспечение для выполнения в определенном порядке, но вы не можете контролировать их порядок, когда они назначены маршруту. В этом случае вы можете указать приоритет промежуточного программного обеспечения, используя $middlewarePriorityсвойство вашего файла:app/Http/Kernel.php

/**
 * The priority-sorted list of middleware.
 *
 * This forces non-global middleware to always be in the given order.
 *
 * @var array
 */
protected $middlewarePriority = [
    \Illuminate\Session\Middleware\StartSession::class,
    \Illuminate\View\Middleware\ShareErrorsFromSession::class,
    \App\Http\Middleware\Authenticate::class,
    \Illuminate\Session\Middleware\AuthenticateSession::class,
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
    \Illuminate\Auth\Middleware\Authorize::class,
];

 

Параметры промежуточного программного обеспечения

Промежуточное программное обеспечение также может получать дополнительные параметры. Например, если вашему приложению необходимо проверить, что прошедший проверку пользователь имеет заданную «роль» перед выполнением заданного действия, вы можете создать CheckRoleпромежуточное программное обеспечение, которое получает имя роли в качестве дополнительного аргумента.

Дополнительные параметры промежуточного программного обеспечения будут переданы промежуточному программному обеспечению после $nextаргумента:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckRole
{
    /**
     * Handle the incoming request.
     *
     * @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);
    }

}

Параметры промежуточного программного обеспечения могут быть указаны при определении маршрута путем разделения имени промежуточного программного обеспечения и параметров с помощью :. Несколько параметров должны быть разделены запятыми:

Route::put('post/{id}', function ($id) {
    //
})->middleware('role:editor');

 

Завершаемое промежуточное ПО

Иногда промежуточному программному обеспечению может потребоваться выполнить некоторую работу после подготовки ответа HTTP. Например, промежуточное программное обеспечение сеанса, включенное в Laravel, записывает данные сеанса в хранилище после полной подготовки ответа. Если вы определяете terminateметод в своем промежуточном программном обеспечении, он будет автоматически вызываться после того, как ответ будет готов к отправке в браузер.

<?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Метод должен получить как запрос и ответ. После того, как вы определили промежуточное промежуточное ПО, вы должны добавить его в список маршрутов или глобального промежуточного ПО в файле.app/Http/Kernel.php

При вызове terminateметода на вашем промежуточном программном обеспечении Laravel разрешит новый экземпляр промежуточного программного обеспечения из сервисного контейнера . Если вы хотели бы использовать тот же экземпляр промежуточного слоя , когда handleи terminateметоды называются, зарегистрировать промежуточный с контейнером с использованием контейнера singleton метода.