// yii\BaseYii\getVersion
public static function getVersion()
{
return '2.0.10';
}
动作过滤器的基类, 有两个重要的变量, 这两个变量都是存储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;
}
该过滤器提供简单的访问控制
$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;
}
该类是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;
}
}
用于验证http请求的方法
public function behaviors()
{
return [
[
'class' => VerbFilter::className(),
// ---------- 指定action的访问规则
'actions' => [
'create' => ['get', 'post'],
'delete' => ['post'],
'upload'=>['post'],
// 其它的都是用get
'*' => ['get']
]
]
];
}
该过滤器将会执行EVENT_BEFORE_ACTION,在动作执行前进行判断, 验证未通过,则action不会继续执行下去。
其余暂未使用到, 有用到再添加