Фильтры контроллеров
Фильтры контроллеров позволяют выполнять действия до или после выполнения контроллеров. В отличие от событий, вы можете выбрать конкретные URI, к которым будут применяться фильтры. Входящие фильтры могут изменять запрос, а фильтры после выполнения могут действовать на ответ и даже изменять его, что обеспечивает большую гибкость и мощность. Некоторые распространённые примеры задач, которые можно выполнить с помощью фильтров:
- Выполнение защиты от CSRF для входящих запросов
- Ограничение доступа к частям сайта в зависимости от роли
- Ограничение скорости запросов на определённые конечные точки
- Отображение страницы «Сервис временно недоступен»
- Автоматическое согласование типа контента
- и многое другое…
Создание фильтра
Фильтры — это простые классы, которые реализуют CodeIgniter\Filters\FilterInterface. Они содержат два метода: before() и after(), которые содержат код, который будет выполняться до и после контроллера соответственно. Ваш класс должен содержать оба метода, но может оставить методы пустыми, если они не нужны. Схема класса фильтра выглядит следующим образом:
<?php
namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
class MyFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
// Do something here
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Do something here
}
}
Фильтры до выполнения
Из любого фильтра вы можете вернуть объект $request и он заменит текущий запрос, позволяя внести изменения, которые останутся при выполнении контроллера.
Поскольку фильтры до выполнения выполняются до выполнения контроллера, вы можете в некоторых случаях захотеть остановить выполнение действий в контроллере. Также, когда у вас есть ряд фильтров, вы можете остановить выполнение последующих фильтров после определенного фильтра. Вы можете легко сделать это, вернув любое непустое значение. Если фильтр до выполнения возвращает пустое значение, действия контроллера или последующие фильтры будут все равно выполнены. Исключением из правила о непустом значении является экземпляр Request. Его возвращение в фильтре до выполнения не остановит выполнение, но только заменит текущий объект $request.
Обычно это используется для перенаправлений, как в этом примере:
public function before(RequestInterface $request, $arguments = null)
{
$auth = service('auth');
if (! $auth->isLoggedIn()) {
return redirect()->to(site_url('login'));
}
}
Если возвращается экземпляр Response , ответ будет отправлен обратно клиенту, и выполнение сценария остановится. Это может быть полезно для реализации ограничения скорости для API. См. Throttler для примера.
Фильтры после выполнения
Фильтры после выполнения почти идентичны фильтрам до выполнения, за исключением того, что вы можете вернуть только объект $response , и вы не можете остановить выполнение сценария. Это позволяет вам изменить конечный вывод или просто сделать что-то с конечным выводом. Это может быть использовано для обеспечения того, что определенные заголовки безопасности были установлены правильно, или для кеширования конечного вывода, или даже для фильтрации конечного вывода с помощью фильтра ненормативной лексики.
Настройка фильтров
После создания фильтров необходимо настроить, когда они будут выполняться. Это делается в файле app/Config/Filters.php. Этот файл содержит четыре свойства, которые позволяют настроить точное время выполнения фильтров.
$aliases
Массив $aliases используется для сопоставления простого имени с одним или несколькими полными именами классов, которые являются фильтрами для выполнения:
public $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
];
Псевдонимы обязательны, и если вы попытаетесь использовать полное имя класса позже, система выдаст ошибку. Определение их таким образом упрощает замену используемого класса. Отлично подходит для случаев, когда вы решили перейти к другой системе аутентификации, поскольку вы меняете только класс фильтра, и все готово.
Вы можете объединить несколько фильтров в один псевдоним, что упрощает применение сложных наборов фильтров:
public $aliases = [
'apiPrep' => [
\App\Filters\Negotiate::class,
\App\Filters\ApiAuth::class,
]
];
Вы должны определить столько псевдонимов, сколько вам нужно.
$globals
Во второй секции вы можете определить любые фильтры, которые должны применяться ко всем запросам, выполняемым фреймворком. Следите за количеством используемых фильтров, так как слишком много фильтров может повлиять на производительность при каждом запросе. Фильтры могут быть указаны путем добавления их псевдонима в массив before или after:
public $globals = [
'before' => [
'csrf',
],
'after' => [],
];
Иногда вам нужно применить фильтр почти ко всем запросам, но оставить некоторые без изменений. Один распространенный пример — если вам нужно исключить несколько URI из фильтра CSRF, чтобы разрешить запросы с сторонних сайтов к одному или двум конкретным URI, сохраняя при этом защиту остальных. Для этого добавьте массив с ключом «except» и URI для сопоставления в качестве значения вместе с псевдонимом:
public $globals = [
'before' => [
'csrf' => ['except' => 'api/*'],
],
'after' => [],
];
В любом месте, где вы можете использовать URI в настройках фильтра, вы можете использовать регулярное выражение или, как в этом примере, использовать звездочку для подстановочного знака, который будет соответствовать всем символам после нее. В этом примере все URL, начинающиеся с api/ , будут исключены из защиты от CSRF, но формы сайта будут защищены. Если вам нужно указать несколько URI, вы можете использовать массив шаблонов URI:
public $globals = [
'before' => [
'csrf' => ['except' => ['foo/*', 'bar/*']],
],
'after' => [],
];
$methods
Вы можете применять фильтры ко всем запросам определенного HTTP-метода, например, POST, GET, PUT и т. д. В этом массиве вы указали бы имя метода в нижнем регистре. Его значением был бы массив фильтров для выполнения. В отличие от свойств $globals или $filters, они будут выполняться только как фильтры до выполнения:
public $methods = [
'post' => ['foo', 'bar'],
'get' => ['baz'],
]
В дополнение к стандартным HTTP-методам, также поддерживается один специальный случай: «cli». Метод «cli» будет применяться ко всем запросам, которые выполнялись из командной строки.
$filters
Это свойство — массив псевдонимов фильтров. Для каждого псевдонима вы можете указать массивы before и after, которые содержат список шаблонов URI, к которым должен применяться фильтр:
public filters = [
'foo' => ['before' => ['admin/*'], 'after' => ['users/*']],
'bar' => ['before' => ['api/*', 'admin/*']],
];
Аргументы фильтров
При настройке фильтров дополнительные аргументы могут передаваться фильтру при настройке маршрута:
$routes->add('users/delete/(:segment)', 'AdminController::index', ['filter' => 'admin-auth:dual,noreturn']);
В этом примере массив ['dual', 'noreturn'] будет передан в $arguments методам реализации фильтра before() и after().
Предоставленные фильтры
В CodeIgniter4 поставляются три фильтра: Honeypot, CSRF, и DebugToolbar.
Примечание
Фильтры выполняются в объявленном порядке, определённом в файле конфигурации, но есть одно исключение, которое касается DebugToolbar, который всегда выполняется последним. Это связано с тем, что DebugToolbar должен иметь возможность регистрировать все, что происходит в других фильтрах.
© 2014–2020 British Columbia Institute of Technology
Licensed under the MIT License.
https://codeigniter.com/user_guide/incoming/filters.html