Yii2 理解filters

简介: 版本ActionFilterAccessControlAccessRuleVerbFilter其它1 版本// yii\BaseYii\getVersionpublic static function getVersion(){ return '2.0.10';}2 ActionFilter动作过滤器的基

1 版本

// yii\BaseYii\getVersion
public static function getVersion()
{
    return '2.0.10';
}

2 ActionFilter

动作过滤器的基类, 有两个重要的变量, 这两个变量都是存储action id

$except: 过滤器将不会应用于在这里面出现的action,即使出现在$only中,过滤器也不会有效。
$only: 如果为空, 该过滤器会应用于其owner下的所有过滤器。如果不为空, 则只应用于在这里面出现的action。

以上规则见代码:

protected function isActive($action)
{
    $id = $this->getActionId($action);
    // 如果为空, 过滤器判断为有效
    if (empty($this->only)) 
    {
        $onlyMatch = true;
    } 
    else 
    {
        // 判断action是否出现在$only中
        $onlyMatch = false;
        foreach ($this->only as $pattern) 
        {
            if (fnmatch($pattern, $id)) 
            {
                $onlyMatch = true;
                break;
            }
        }
    }
    // --------- 拦路虎: 在这里面出现,即使前面判断过滤器有效, 也会变为无效
    $exceptMatch = false;
    foreach ($this->except as $pattern) 
    {
        if (fnmatch($pattern, $id)) 
        {
            $exceptMatch = true;
            break;
        }
    }

    return !$exceptMatch && $onlyMatch;
}

3 AccessControl

该过滤器提供简单的访问控制

$user: 将会指向User,用于判断玩家的情况, 比如 $user->getIsGuest()判断玩家是否是游客。
$denyCallback: 如果没有通过过滤器, 将会指向denyCallback指向的回调函数, 如果没有设置,就会读取默认的denyAccess
protected function denyAccess($user)
{
    // 如果是游客, 则跳珠到登陆界面
    if ($user->getIsGuest()) 
    {
        // 如果没有定义登陆界面,则会报异常
        $user->loginRequired();
    } 
    else 
    {
        throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
    }
}
$ruleConfig: 默认的规则,指向yii\filters\AccessRule, 这个规则在后文讲述
$rules: 自定义的规则, 将会和$ruleConfig进行合并, 如果有相同项,会覆盖$ruleConfig
// 基类Object的构造函数中调用
public function init()
{
    parent::init();
    $this->user = Instance::ensure($this->user, User::className());
    foreach ($this->rules as $i => $rule) 
    {
        if (is_array($rule)) 
        {
            // 如果没有更改$ruleConfig变量, 这里将rule配置一一生成AccessRule对象
            $this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
        }
    }
}

客户端在请求的时候,会创建$controller, $action,然后执行$controller->runAction($action, …), 在runAction中,将会先执行过滤器的beforeAction,在这里也就是yii\filters\AccessController::beforeAction

具体流程见Yii2 分析Controller::behaviors 触发过程
http://blog.csdn.net/alex_my/article/details/54172619

public function beforeAction($action)
{
    $user = $this->user;
    $request = Yii::$app->getRequest();

    foreach ($this->rules as $rule) 
    {
        // --------------- $rule->allows将在下文分析
        if ($allow = $rule->allows($action, $user, $request)) 
        {
            return true;
        } 
        // --------------- 如果有定义denyCallback,则调用
        // --------------- 否则调用默认的denyAccess
        elseif ($allow === false) 
        {
            if (isset($rule->denyCallback)) 
            {
                call_user_func($rule->denyCallback, $rule, $action);
            } 
            elseif ($this->denyCallback !== null)
            {
                call_user_func($this->denyCallback, $rule, $action);
            } 
            else 
            {
                $this->denyAccess($user);
            }
            return false;
        }
    }
    if ($this->denyCallback !== null) 
    {
        call_user_func($this->denyCallback, null, $action);
    } 
    else 
    {
        $this->denyAccess($user);
    }
    return false;
}

4 AccessRule

该类是AccessController的规则对象,其成员变量和AccessController中的rules合并,且相同键名的会被后者覆盖

$allow: 如果为true, 如果规则验证通过, 则表示该规则通过验证。如果为false,表示该规则一定不能通过。
$actions: 表示该规则应用于哪些action中, 如果为空, 则表示应用于所有的action中
$controllers: 表示该规则应用于哪些controller中,假设有BaseController::Controller做为自定义的控制器基类,在BaseController::behaviors可以设置规则只用于哪些派生类中:
public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['login', 'error', 'register', 'offline'],
                    'allow' => true,
                    'controllers' => [
                        'site'
                    ]
                ]
            ]
        ]
    ];
$roles: 指定该规则应用于哪些角色, 比如在rules中添加roles => ['Wang']
有两个特殊的角色:
?: 表示未登陆的游客
@: 表示已登陆的角色
$ips: 验证ip
$verbs: 指定该规则应用于哪些请求方法,比如GET, POST
$matchCallback: 通过调用自定义的函数来判断规则是否通过
$denyCallback: 表示验证未通过将会调用的函数

验证过程:

public function allows($action, $user, $request)
{
    if ($this->matchAction($action)
        && $this->matchRole($user)
        && $this->matchIP($request->getUserIP())
        && $this->matchVerb($request->getMethod())
        && $this->matchController($action->controller)
        && $this->matchCustom($action)
    ) 
    {
        return $this->allow ? true : false;
    } 
    else 
    {
        return null;
    }
}

5 VerbFilter

用于验证http请求的方法

public function behaviors()
{
    return [
        [
            'class' => VerbFilter::className(),
            // ---------- 指定action的访问规则
            'actions' => [
                'create' => ['get', 'post'],
                'delete' => ['post'],
                'upload'=>['post'],
                // 其它的都是用get
                '*' => ['get']
            ]
        ]
    ];
}

该过滤器将会执行EVENT_BEFORE_ACTION,在动作执行前进行判断, 验证未通过,则action不会继续执行下去。

6 其它

其余暂未使用到, 有用到再添加

相关文章
|
5月前
|
JavaScript 前端开发
vue filters过滤器传多个参数
这段内容展示了如何在HTML和JavaScript中使用过滤器(filter)。在HTML中,通过`{{变量 | 过滤器名(参数)}}`的方式传递参数给过滤器。在JavaScript中,定义过滤器函数并接收参数,如`filterAa(aa, bb, cc)`,其中`aa`, `bb`, `cc`分别代表过滤器接收到的第1至第3个参数。示例逐步演示了传1个、2个到3个参数给过滤器的过程。
484 1
|
6月前
|
JavaScript
【Vue】过滤器Filters
【Vue】过滤器Filters
|
Oracle 关系型数据库 MySQL
Yii2的基本要求是什么?
Yii2的基本要求是什么?
157 0
|
缓存 开发框架 安全
Yii2是什么?
Yii2是什么?
297 0
|
缓存 安全 数据处理
Yii2相对于Yii1有哪些改进?
Yii2相对于Yii1有哪些改进?
|
JavaScript 前端开发
Vue3不支持Filters过滤器
Vue3不支持Filters过滤器
321 0
|
API 数据安全/隐私保护
5.WebAPI的Filter
1.WebApi的Filter介绍: 大家知道什么是AOP(aspect oriented programming)吗?它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
1560 0
Yii Model
REFs 自动生成代码 创建第一个Yii应用 创建模型 Yii 用户登陆机制
1107 0
|
PHP Windows 前端开发
Yii 初识
接管一个Yii的系统,因为没有文档,所以非常上火。 01 查版本 Yii::getVersion(); 02 生成webapp Yii 是支持通过命令行生成webapp的。其中, yiic.bat是Windows 下的 yiic 命令行脚本。
1276 0