|
|
|
<?php
|
|
|
|
/**
|
|
|
|
* @link http://www.yiiframework.com/
|
|
|
|
* @copyright Copyright (c) 2008 Yii Software LLC
|
|
|
|
* @license http://www.yiiframework.com/license/
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace yii\web;
|
|
|
|
|
|
|
|
use yii\base\Component;
|
|
|
|
use yii\base\Action;
|
|
|
|
|
|
|
|
/**
|
|
|
|
*
|
|
|
|
* @author Qiang Xue <qiang.xue@gmail.com>
|
|
|
|
* @since 2.0
|
|
|
|
*/
|
|
|
|
class AccessRule extends Component
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* @var boolean whether this is an 'allow' rule or 'deny' rule.
|
|
|
|
*/
|
|
|
|
public $allow;
|
|
|
|
/**
|
|
|
|
* @var array list of action IDs that this rule applies to. The comparison is case-sensitive.
|
|
|
|
* If not set or empty, it means this rule applies to all actions.
|
|
|
|
*/
|
|
|
|
public $actions;
|
|
|
|
/**
|
|
|
|
* @var array list of controller IDs that this rule applies to. The comparison is case-sensitive.
|
|
|
|
* If not set or empty, it means this rule applies to all controllers.
|
|
|
|
*/
|
|
|
|
public $controllers;
|
|
|
|
/**
|
|
|
|
* @var array list of roles that this rule applies to. Two special roles are recognized, and
|
|
|
|
* they are checked via [[User::isGuest]]:
|
|
|
|
*
|
|
|
|
* - `?`: matches a guest user (not authenticated yet)
|
|
|
|
* - `@`: matches an authenticated user
|
|
|
|
*
|
|
|
|
* Using additional role names requires RBAC (Role-Based Access Control), and
|
|
|
|
* [[User::checkAccess()]] will be called.
|
|
|
|
*
|
|
|
|
* If this property is not set or empty, it means this rule applies to all roles.
|
|
|
|
*/
|
|
|
|
public $roles;
|
|
|
|
/**
|
|
|
|
* @var array list of user IP addresses that this rule applies to. An IP address
|
|
|
|
* can contain the wildcard `*` at the end so that it matches IP addresses with the same prefix.
|
|
|
|
* For example, '192.168.*' matches all IP addresses in the segment '192.168.'.
|
|
|
|
* If not set or empty, it means this rule applies to all IP addresses.
|
|
|
|
* @see Request::userIP
|
|
|
|
*/
|
|
|
|
public $ips;
|
|
|
|
/**
|
|
|
|
* @var array list of request methods (e.g. `GET`, `POST`) that this rule applies to.
|
|
|
|
* The request methods must be specified in uppercase.
|
|
|
|
* If not set or empty, it means this rule applies to all request methods.
|
|
|
|
* @see Request::requestMethod
|
|
|
|
*/
|
|
|
|
public $verbs;
|
|
|
|
/**
|
|
|
|
* @var callback a callback that will be called to determine if the rule should be applied.
|
|
|
|
* The signature of the callback should be as follows:
|
|
|
|
*
|
|
|
|
* ~~~
|
|
|
|
* function ($rule, $action)
|
|
|
|
* ~~~
|
|
|
|
*
|
|
|
|
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object.
|
|
|
|
* The callback should return a boolean value indicating whether this rule should be applied.
|
|
|
|
*/
|
|
|
|
public $matchCallback;
|
|
|
|
/**
|
|
|
|
* @var callback a callback that will be called if this rule determines the access to
|
|
|
|
* the current action should be denied. If not set, the behavior will be determined by
|
|
|
|
* [[AccessControl]].
|
|
|
|
*
|
|
|
|
* The signature of the callback should be as follows:
|
|
|
|
*
|
|
|
|
* ~~~
|
|
|
|
* function ($rule, $action)
|
|
|
|
* ~~~
|
|
|
|
*
|
|
|
|
* where `$rule` is this rule, and `$action` is the current [[Action|action]] object.
|
|
|
|
*/
|
|
|
|
public $denyCallback;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks whether the Web user is allowed to perform the specified action.
|
|
|
|
* @param Action $action the action to be performed
|
|
|
|
* @param User $user the user object
|
|
|
|
* @param Request $request
|
|
|
|
* @return boolean|null true if the user is allowed, false if the user is denied, null if the rule does not apply to the user
|
|
|
|
*/
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Action $action the action
|
|
|
|
* @return boolean whether the rule applies to the action
|
|
|
|
*/
|
|
|
|
protected function matchAction($action)
|
|
|
|
{
|
|
|
|
return empty($this->actions) || in_array($action->id, $this->actions, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Controller $controller the controller
|
|
|
|
* @return boolean whether the rule applies to the controller
|
|
|
|
*/
|
|
|
|
protected function matchController($controller)
|
|
|
|
{
|
|
|
|
return empty($this->controllers) || in_array($controller->uniqueId, $this->controllers, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param User $user the user object
|
|
|
|
* @return boolean whether the rule applies to the role
|
|
|
|
*/
|
|
|
|
protected function matchRole($user)
|
|
|
|
{
|
|
|
|
if (empty($this->roles)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
foreach ($this->roles as $role) {
|
|
|
|
if ($role === '?' && $user->getIsGuest()) {
|
|
|
|
return true;
|
|
|
|
} elseif ($role === '@' && !$user->getIsGuest()) {
|
|
|
|
return true;
|
|
|
|
} elseif ($user->checkAccess($role)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $ip the IP address
|
|
|
|
* @return boolean whether the rule applies to the IP address
|
|
|
|
*/
|
|
|
|
protected function matchIP($ip)
|
|
|
|
{
|
|
|
|
if (empty($this->ips)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
foreach ($this->ips as $rule) {
|
|
|
|
if ($rule === '*' || $rule === $ip || (($pos = strpos($rule, '*')) !== false && !strncmp($ip, $rule, $pos))) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $verb the request method
|
|
|
|
* @return boolean whether the rule applies to the request
|
|
|
|
*/
|
|
|
|
protected function matchVerb($verb)
|
|
|
|
{
|
|
|
|
return empty($this->verbs) || in_array($verb, $this->verbs, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param Action $action the action to be performed
|
|
|
|
* @return boolean whether the rule should be applied
|
|
|
|
*/
|
|
|
|
protected function matchCustom($action)
|
|
|
|
{
|
|
|
|
return empty($this->matchCallback) || call_user_func($this->matchCallback, $this, $action);
|
|
|
|
}
|
|
|
|
}
|