You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
188 lines
5.3 KiB
188 lines
5.3 KiB
<?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; |
|
use yii\base\Controller; |
|
use yii\web\User; |
|
use yii\web\Request; |
|
|
|
/** |
|
* |
|
* @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::hasAccess()]] 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->getRequestMethod()) |
|
&& $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->id, $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); |
|
} |
|
} |