Фильтры
Фильтры — это объекты, которые выполняются до и/или после действий контроллера. Например, фильтр контроля доступа может выполняться до действий, чтобы убедиться, что к ним разрешен доступ определённым конечным пользователям; фильтр сжатия содержимого может выполняться после действий, чтобы сжать содержимое ответа перед отправкой конечным пользователям.
Фильтр может состоять из предобработки (логика фильтрации, применяемая до действий) и/или послеобработки (логика, применяемая после действий).
Использование фильтров
Фильтры по существу являются особым видом поведений. Поэтому использование фильтров такое же, как и использование поведений. Вы можете объявлять фильтры в классе контроллера, переопределяя его метод behaviors(), как показано ниже:
public function behaviors()
{
return [
[
'class' => 'yii\filters\HttpCache',
'only' => ['index', 'view'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
По умолчанию фильтры, объявленные в классе контроллера, будут применяться ко всем действиям в этом контроллере. Однако вы можете явно указать, к каким действиям должен применяться фильтр, настроив свойство only. В приведенном выше примере фильтр HttpCache применяется только к действиям index и view. Вы также можете настроить свойство except, чтобы поместить некоторые действия в список исключений для фильтрации.
Помимо контроллеров, вы также можете объявлять фильтры в модуле или приложении. В этом случае фильтры будут применяться ко всем действиям контроллеров, принадлежащим этому модулю или приложению, если вы не настроили свойства фильтров only и except, как описано выше.
Примечание: При объявлении фильтров в модулях или приложениях следует использовать маршруты вместо идентификаторов действий в свойствах only и except. Это связано с тем, что сами идентификаторы действий не могут полностью указать действия в рамках модуля или приложения.
Если для одного действия настроены несколько фильтров, они применяются в соответствии с правилами, описанными ниже:
- Предварительная фильтрация
- Применить фильтры, объявленные в приложении, в порядке их перечисления в
behaviors(). - Применить фильтры, объявленные в модуле, в порядке их перечисления в
behaviors(). - Применить фильтры, объявленные в контроллере, в порядке их перечисления в
behaviors(). - Если какой-либо из фильтров отменяет выполнение действия, то фильтры (как предварительной, так и последующей обработки), расположенные после него, не будут применяться.
- Применить фильтры, объявленные в приложении, в порядке их перечисления в
- Выполнение действия, если оно прошло предварительную фильтрацию.
- Последующая фильтрация
- Применить фильтры, объявленные в контроллере, в обратном порядке их перечисления в
behaviors(). - Применить фильтры, объявленные в модуле, в обратном порядке их перечисления в
behaviors(). - Применить фильтры, объявленные в приложении, в обратном порядке их перечисления в
behaviors().
- Применить фильтры, объявленные в контроллере, в обратном порядке их перечисления в
Создание фильтров
Чтобы создать новый фильтр действий, необходимо расширить класс yii\base\ActionFilter и переопределить методы beforeAction() и/или afterAction(). Первый из них выполняется до запуска действия, а второй — после. Значение возвращаемого методом beforeAction() определяет, должно ли выполняться действие или нет. Если оно false, фильтры, следующие за ним, будут пропущены, и действие не будет выполнено.
Следующий пример демонстрирует фильтр, который регистрирует время выполнения действия:
namespace app\components;
use Yii;
use yii\base\ActionFilter;
class ActionTimeFilter extends ActionFilter
{
private $_startTime;
public function beforeAction($action)
{
$this->_startTime = microtime(true);
return parent::beforeAction($action);
}
public function afterAction($action, $result)
{
$time = microtime(true) - $this->_startTime;
Yii::trace("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}
Основные фильтры
Yii предоставляет набор часто используемых фильтров, расположенных в основном в пространстве имён yii\filters. Далее мы кратко рассмотрим эти фильтры.
AccessControl
AccessControl обеспечивает простой контроль доступа на основе набора правил. В частности, перед выполнением действия AccessControl проверит перечисленные правила и найдёт первое, соответствующее текущим переменным контекста (например, IP-адрес пользователя, состояние входа пользователя и т. д.). Соответствующее правило будет определять, разрешено ли выполнение запрошенного действия или нет. Если ни одно правило не соответствует, доступ будет запрещён.
В следующем примере показано, как разрешить аутентифицированным пользователям доступ к действиям create и update, в то же время запретив всем остальным пользователям доступ к этим двум действиям.
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create', 'update'],
'rules' => [
// allow authenticated users
[
'allow' => true,
'roles' => ['@'],
],
// everything else is denied by default
],
],
];
}
Для получения более подробной информации о контроле доступа в целом обратитесь к разделу Авторизация.
Фильтры методов аутентификации
Фильтры методов аутентификации используются для аутентификации пользователя с помощью различных методов, таких как HTTP Basic Auth, OAuth 2. Все эти классы фильтров находятся в пространстве имён yii\filters\auth.
В следующем примере показано, как использовать yii\filters\auth\HttpBasicAuth для аутентификации пользователя с помощью маркера доступа на основе метода HTTP Basic Auth. Обратите внимание, что для этого ваша класс пользователя должен реализовывать метод findIdentityByAccessToken().
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return [
'basicAuth' => [
'class' => HttpBasicAuth::className(),
],
];
}
Фильтры методов аутентификации обычно используются при реализации RESTful API. Для получения более подробной информации обратитесь к разделу RESTful Аутентификация.
ContentNegotiator
ContentNegotiator поддерживает согласование форматов ответов и языков приложений. Он будет пытаться определить формат и/или язык ответа, анализируя параметры GET и заголовок HTTP Accept.
В следующем примере ContentNegotiator настроен для поддержки форматов ответов JSON и XML, а также языков английский (США) и немецкий.
use yii\filters\ContentNegotiator;
use yii\web\Response;
public function behaviors()
{
return [
[
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
];
}
Форматы и языки ответов часто необходимо определять намного раньше на этапе жизненного цикла приложения. По этой причине ContentNegotiator разработан таким образом, чтобы его можно было использовать как компонент инициализации помимо использования в качестве фильтра. Например, вы можете настроить его в конфигурации приложения, как показано ниже:
use yii\filters\ContentNegotiator;
use yii\web\Response;
[
'bootstrap' => [
[
'class' => ContentNegotiator::className(),
'formats' => [
'application/json' => Response::FORMAT_JSON,
'application/xml' => Response::FORMAT_XML,
],
'languages' => [
'en-US',
'de',
],
],
],
];
Информация: В случае, если предпочтительный тип содержимого и язык не могут быть определены из запроса, будет использован первый формат и язык, перечисленный в formats и languages.
HttpCache
HttpCache реализует кэширование на стороне клиента, используя заголовки HTTP Last-Modified и Etag. Например,
use yii\filters\HttpCache;
public function behaviors()
{
return [
[
'class' => HttpCache::className(),
'only' => ['index'],
'lastModified' => function ($action, $params) {
$q = new \yii\db\Query();
return $q->from('user')->max('updated_at');
},
],
];
}
Для получения дополнительной информации об использовании HttpCache обратитесь к разделу Кэширование HTTP.
PageCache
PageCache реализует кэширование целых страниц на стороне сервера. В следующем примере PageCache применяется к действию index для кэширования всей страницы на срок до 60 секунд или до тех пор, пока не изменится количество записей в таблице post. Он также сохраняет разные версии страницы в зависимости от выбранного языка приложения.
use yii\filters\PageCache;
use yii\caching\DbDependency;
public function behaviors()
{
return [
'pageCache' => [
'class' => PageCache::className(),
'only' => ['index'],
'duration' => 60,
'dependency' => [
'class' => DbDependency::className(),
'sql' => 'SELECT COUNT(*) FROM post',
],
'variations' => [
\Yii::$app->language,
]
],
];
}
Для получения дополнительной информации об использовании PageCache обратитесь к разделу Кэширование страниц.
RateLimiter
RateLimiter реализует алгоритм ограничения скорости на основе алгоритма «дырявый ящик». Он используется в основном при реализации RESTful API. Для получения подробной информации об использовании этого фильтра обратитесь к разделу Ограничение скорости.
VerbFilter
VerbFilter проверяет, разрешены ли HTTP-методы запроса для запрошенных действий. Если они не разрешены, будет выброшено исключение HTTP 405. В следующем примере VerbFilter объявлен для указания типичного набора разрешенных методов запроса для действий CRUD.
use yii\filters\VerbFilter;
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'index' => ['get'],
'view' => ['get'],
'create' => ['get', 'post'],
'update' => ['get', 'put', 'post'],
'delete' => ['post', 'delete'],
],
],
];
}
Cors
Cross-origin resource sharing CORS — это механизм, который позволяет многим ресурсам (например, шрифтам, JavaScript и т. д.) на веб-странице запрашиваться из другого домена, отличного от домена происхождения ресурса. В частности, вызовы AJAX JavaScript могут использовать механизм XMLHttpRequest. Такие "междоменные" запросы в противном случае были бы запрещены веб-браузерами в соответствии с политикой безопасности одного источника. CORS определяет способ взаимодействия браузера и сервера для определения возможности разрешения междоменного запроса.
Фильтр Cors должен быть определён до фильтров аутентификации/авторизации, чтобы гарантировать, что заголовки CORS всегда будут отправляться.
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
],
], parent::behaviors());
}
Также ознакомьтесь с разделом REST-контроллеры, если вы хотите добавить фильтр CORS к классу yii\rest\ActiveController в вашем API.
Фильтрацию CORS можно настроить с помощью свойства $cors.
-
cors['Origin']: массив, используемый для определения разрешенных источников. Может быть['*'](все) или['http://www.myserver.net', 'http://www.myotherserver.com']. По умолчанию['*']. -
cors['Access-Control-Request-Method']: массив разрешенных методов, таких как['GET', 'OPTIONS', 'HEAD']. По умолчанию['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']. -
cors['Access-Control-Request-Headers']: массив разрешенных заголовков. Может быть['*']все заголовки или конкретные заголовки['X-Request-With']. По умолчанию['*']. -
cors['Access-Control-Allow-Credentials']: определяет, может ли текущий запрос выполняться с использованием учетных данных. Может бытьtrue,falseилиnull(не задано). По умолчаниюnull. -
cors['Access-Control-Max-Age']: определяет время жизни запроса предварительного пролёта. По умолчанию86400.
Например, разрешить CORS для источника : http://www.myserver.net с методами GET, HEAD и OPTIONS :
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
],
], parent::behaviors());
}
Вы можете настроить заголовки CORS, переопределяя параметры по умолчанию для каждого действия. Например, добавление Access-Control-Allow-Credentials для действия login можно сделать так:
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
'cors' => [
'Origin' => ['http://www.myserver.net'],
'Access-Control-Request-Method' => ['GET', 'HEAD', 'OPTIONS'],
],
'actions' => [
'login' => [
'Access-Control-Allow-Credentials' => true,
]
]
],
], parent::behaviors());
}
© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-structure-filters.html