[Yii2笔记]040过滤器(Filters) [ 技术分享 ]
说明
学习Yii Framework 2(易2框架)的过程是漫长的,也是充满乐趣的,以下是我学习Yii2框架时对官网英文资料(请参见原文网址)的翻译和代码实现,提供了较完整的代码,供你参考。不妥之处,请多多指正!
原文网址:
http://www.yiiframework.com/doc-2.0/guide-structure-filters.html
本文主题:过滤器(Filters)
过滤器是在控制器动作之前或之后运行的对象。举例来说,一个权限控制器可以在动作运行之前执行,以确保该动作可以被允许的用户所访问;一个内容压缩过滤器可以在动作运行之后运行,这样可以在发送到终端用户之前将内容进行压缩操作。 一个过滤器可以同时由pre-filter(前置过滤器,过滤逻辑应用于动作之前)和post-filter(后置过滤器,过滤逻辑应用于动作之后)共同组成。
1、Using Filters(使用过滤器)
过滤器本质上是一种特殊的behaviors。所以,使用过滤器和使用行为的方法是相同的,你可以在一个控制器类中重写它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属性中使用routes,而不是动作ID。这是因为在模块或应用范围内,动作ID描述的不完整。
当为一个动作配置了多个过滤器时,它们的应用规则如下: 1、Pre-filtering(前置过滤器): 1)执行在应用的behaviors()中定义的过滤器,列出顺序就是它们的执行顺序。 2)执行在模块的behaviors()中定义的过滤器,列出顺序就是它们的执行顺序。 3)执行在控制器的behaviors()中定义的过滤器,列出顺序就是它们的执行顺序。 4)如果任何一个过滤器取消了动作的执行,它之后的过滤器(包括前置和后置)将不再被执行。 2、如果通过前置过滤器,则运行此动作 3、Post-filtering(后置过滤器) 1)执行在控制器的behaviors()中定义的过滤器,列出顺序的反序就是它们的执行顺序。 2)执行在模块的behaviors()中定义的过滤器,列出顺序的反序就是它们的执行顺序。 3)执行在应用的behaviors()中定义的过滤器,列出顺序的反序就是它们的执行顺序。
2、Creating Filters(创建过滤器)
要创建一个新的动作过滤器,应继承自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);
}
}
3、Core Filters(核心过滤器)
Yii提供了一系列通用过滤器,主要构建在yii\filters命名空间下,接下来,我们将主要介绍这些过滤器。
AccessControl Authentication Method Filters ContentNegotiator HttpCache PageCache RateLimiter VerbFilter Cors
AccessControl(访问控制)
AccessControl提供了基于一套规则的简单访问控制,实际上,在一个动作执行之前,AccessControl将检查列出的规则,以查找出符合当前环境变量的(如用户IP地址、用户登录状态等),匹配的规则将决定是放行或拒绝请求动作的执行。如果没有规则匹配,则访问将被拒绝。
下例将展示如何允许认证用户访问create和update动作,但对其他用户拒绝访问这两个方法:
use yii\filters\AccessControl;
public function behaviors(){
return [
'access'=>[
'class'=>AccessControl::className(),
'only'=>['access','update'],
'rules'=>[
//允许认证用户访问
[
'allow'=>true,
'roles'=>['@'],
],
//默认情况下其他人都将被拒绝访问
],
],
];
}
关于访问控制的详细信息,请参考Authorization章节: http://www.yiiframework.com/doc-2.0/guide-security-authorization.html
Authentication Method Filters(授权方法过滤器)
授权方法过滤器用于使用不同的方法授权一个用户,例如HTTP Basic Auth,OAuth2 。此过滤器类在yii\filters\auth命名空间下。
下例展示了如何使用yii\filters\auth\HttpBasicAuth授权一个用户使用基于HTTP Basic Auth方法获取访问令牌。注意要让这段代码正常工作,需要在user标识类中实现findIdentityByAccessToken()方法。
use yii\filters\auth\HttpBasicAuth;
public function behaviors(){
return [
'basicAuth' =>[
'class'=>HttpBasicAuth::className(),
],
];
}
授权方法过滤器通常用于实现RESTful API,更多细节请参考RESTful的Authentication章节: http://www.yiiframework.com/doc-2.0/guide-rest-authentication.html
ContentNegotiator(内容协商)
ContentNegotiator支持响应格式协商和语言协商。它将通过检查GET参数和Accept HTTP头令牌去决定响应格式和语言。 在下例中,配置的内容协商将支持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'=>FORMAT_XML,
],
'language'=>[
'en-US',
'de',
],
],
];
}
响应格式和语言通常需要在应用生命周期中更早的被决定下来,因为这个原因,ContentNegotiator更应被设计为一个启动组件(bootstrapping component)而不是一个过滤器,你可以在应用配置中如下设置:
[
'bootstrap' =>[
[
'class'=>'yii\filters\ContentNegotiator',
'formats'=>[
'application/json'=>yii\web\Response::FORMAT_JSON,
'application/xml'=>yii\web\Response::FOMAT_XML,
],
'language'=>[
'en-US',
'de',
],
],
],
];
信息:首选的内容类型和语言如果不能从请求中确定,那么在格式和语言设置中的第一项将被使用。
HttpCache(Http缓存)
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 Caching章节: http://www.yiiframework.com/doc-2.0/guide-caching-http.html
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的使用详情请参考Page Caching章节: http://www.yiiframework.com/doc-2.0/guide-caching-page.html
RateLimiter(频率限制器)
频率限制器基于Leaky bucket算法(漏桶算法)实现了频率限制。它主要用于实现RESTful API,关于这个过滤器的使用详情请参考Rate Limiting章节: http://www.yiiframework.com/doc-2.0/guide-rest-rate-limiting.html
VerbFilter(动词过滤器)
VerbFilter检查HTTP请求方法是否使用的是允许的动作。如果是非允许的,它将抛出一个HTTP405异常,在下例中,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(Cross-origin resource sharing,跨域资源共享)是允许外域访问资源域网页资源的一种机制。特别是JavaScript的AJAX调用可以使用XMLHttpRequest的机制。根据同源安装策略,这样的跨域(cross-domain)请求将被浏览器禁止。CORS在浏览器与服务器之间定义了一个方法,交互决定是否允许此跨域请求。
Cors过滤器将在Authentication/Authorization过滤器之前定义,以确保CORS头信息会始终被发送出去:
use yii\filters\Cors;
use yii\helpers\ArrayHelper;
public function behaviors(){
return ArrayHelper::merge([
[
'class'=>Cors::className(),
],
],parent::behaviors());
}
在你的API中如果你想要添加CORS过滤器到yii\rest\ActiveController类中,请参阅REST Controllers章节: http://www.yiiframework.com/doc-2.0/guide-rest-controllers.html#cors
Cors过滤器可以使用$cors 属性进行调节: 1、cors['Origin']:定义允许源的数组,可以是'*'或['http://www.myserver.net','http://www.myotherserver.com'],默认值为['*'] 2、cors['Access-Control-Request-Method']:允许动词的数组,如['GET','OPTIONS','HEAD']。默认值是['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS']。 3、cors['Access-Control-Request-Headers']:允许头信息的数组。可以是['*'](所有头)或定义一个['X-Request-With'],默认值是['*']。 4、cors['Access-Control-Allow-Credentials']:定义当前请求是否使用了证书,可以是true,false或null(没有设置),默认值为 null。 5、cors['Access-Control-Max-Age']:定义请求准备的时长,默认值是86400。
例如,允许CORS使用GET,HEAD和OPTIONS方法调用http://www.myserver.net:
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-Reuqest-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());
}
(全文完)
共 3 条回复
阿江
最后登录:2024-03-03
在线时长:186小时21分
- 粉丝94
- 金钱16816
- 威望160
- 积分20276