過濾器
過濾器是 控制器動作 執行之前或之後執行的對象。 例如訪問控制過濾器可在動作執行之前來控制特殊終端用戶是否有權限執行動作, 內容壓縮過濾器可在動作執行之後發給終端用戶之前壓縮響應內容。
過濾器可包含 預過濾(過濾邏輯在動作_之前_) 或 後過濾(過濾邏輯在動作_之後_), 也可同時包含兩者。
使用過濾器
過濾器本質上是一類特殊的 行爲, 所以使用過濾器和 使用 行爲一樣。 可以在控制器類中覆蓋它的 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 屬性中使用路由 代替動作ID, 因爲在模塊或應用主體中只用動作ID並不能唯一指定到具體動作。
當一個動作有多個過濾器時,根據以下規則先後執行:
- 預過濾
- 按順序執行應用主體中
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::debug("Action '{$action->uniqueId}' spent $time second.");
return parent::afterAction($action, $result);
}
}
核心過濾器
Yii 提供了一組常用過濾器,在 yii\filters
命名空間下, 接下來我們簡要介紹這些過濾器。
AccessControl
AccessControl 提供基於 rules 規則的訪問控制。 特別是在動作執行之前,訪問控制會檢測所有規則 並找到第一個符合上下文的變量(比如用戶IP地址、登錄狀態等等)的規則, 來決定允許還是拒絕請求動作的執行, 如果沒有規則符合,訪問就會被拒絕。
如下示例表示表示允許已認證用戶訪問 create
和 update
動作, 拒絕其他用戶訪問這兩個動作。
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['create', 'update'],
'rules' => [
// 允許認證用戶
[
'allow' => true,
'roles' => ['@'],
],
// 默認禁止其他用戶
],
],
];
}
更多關於訪問控制的詳情請參閱 授權 一節。
認證方法過濾器
認證方法過濾器通過HTTP Basic Auth 或OAuth 2 來認證一個用戶,認證方法過濾器類在 yii\filters\auth
命名空間下。
如下示例表示可使用yii\filters\auth\HttpBasicAuth來認證一個用戶, 它使用基於HTTP基礎認證方法的令牌。 注意爲了可運行,user identity class 類必須 實現 findIdentityByAccessToken()方法。
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
return [
'basicAuth' => [
'class' => HttpBasicAuth::className(),
],
];
}
認證方法過濾器通常在實現RESTful API中使用, 更多關於訪問控制的詳情請參閱 RESTful 認證 一節。
ContentNegotiator
ContentNegotiator支持響應內容格式處理和語言處理。 通過檢查 GET
參數和 Accept
HTTP頭部來決定響應內容格式和語言。
如下示例,配置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 利用 Last-Modified
和 Etag
HTTP頭實現客戶端緩存。 例如:
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 APIs,更多關於該過濾器詳情請參閱 Rate Limiting 一節。
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
跨域資源共享 CORS 機制允許一個網頁的許多資源(例如字體、JavaScript等) 這些資源可以通過其他域名訪問獲取。 特別是 JavaScript 的 AJAX 調用可使用 XMLHttpRequest 機制, 由於同源安全策略該跨域請求會被網頁瀏覽器禁止. CORS定義瀏覽器和服務器交互時哪些跨域請求允許和禁止。
Cors filter 應在 授權 / 認證 過濾器之前定義, 以保證CORS頭部被髮送。
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors()
{
return ArrayHelper::merge([
[
'class' => Cors::className(),
],
], parent::behaviors());
}
如果要將CORS過濾器添加到你的 API 中的 yii\rest\ActiveController 類, 還要檢查 REST Controllers 中的部分。
CROS過濾器可以通過 [KaTeX parse error: Expected 'EOF', got '#' at position 60: …ii-filters-cors#̲cors-detail) 屬性進行調整。
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
。
例如,允許來源爲 http://www.myserver.net
和方式爲 GET
,HEAD
和 OPTIONS
的 CORS 如下:
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 頭部。例如,爲 login
動作 增加 Access-Control-Allow-Credentials
參數如下所示:
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());
}