AccessControl.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\filters;
  8. use Yii;
  9. use yii\base\Action;
  10. use yii\base\ActionFilter;
  11. use yii\di\Instance;
  12. use yii\web\ForbiddenHttpException;
  13. use yii\web\User;
  14. /**
  15. * AccessControl provides simple access control based on a set of rules.
  16. *
  17. * AccessControl is an action filter. It will check its [[rules]] to find
  18. * the first rule that matches the current context variables (such as user IP address, user role).
  19. * The matching rule will dictate whether to allow or deny the access to the requested controller
  20. * action. If no rule matches, the access will be denied.
  21. *
  22. * To use AccessControl, declare it in the `behaviors()` method of your controller class.
  23. * For example, the following declarations will allow authenticated users to access the "create"
  24. * and "update" actions and deny all other users from accessing these two actions.
  25. *
  26. * ```php
  27. * public function behaviors()
  28. * {
  29. * return [
  30. * 'access' => [
  31. * 'class' => \yii\filters\AccessControl::className(),
  32. * 'only' => ['create', 'update'],
  33. * 'rules' => [
  34. * // deny all POST requests
  35. * [
  36. * 'allow' => false,
  37. * 'verbs' => ['POST']
  38. * ],
  39. * // allow authenticated users
  40. * [
  41. * 'allow' => true,
  42. * 'roles' => ['@'],
  43. * ],
  44. * // everything else is denied
  45. * ],
  46. * ],
  47. * ];
  48. * }
  49. * ```
  50. *
  51. * @author Qiang Xue <qiang.xue@gmail.com>
  52. * @since 2.0
  53. */
  54. class AccessControl extends ActionFilter
  55. {
  56. /**
  57. * @var User|array|string|false the user object representing the authentication status or the ID of the user application component.
  58. * Starting from version 2.0.2, this can also be a configuration array for creating the object.
  59. * Starting from version 2.0.12, you can set it to `false` to explicitly switch this component support off for the filter.
  60. */
  61. public $user = 'user';
  62. /**
  63. * @var callable a callback that will be called if the access should be denied
  64. * to the current user. This is the case when either no rule matches, or a rule with
  65. * [[AccessRule::$allow|$allow]] set to `false` matches.
  66. * If not set, [[denyAccess()]] will be called.
  67. *
  68. * The signature of the callback should be as follows:
  69. *
  70. * ```php
  71. * function ($rule, $action)
  72. * ```
  73. *
  74. * where `$rule` is the rule that denies the user, and `$action` is the current [[Action|action]] object.
  75. * `$rule` can be `null` if access is denied because none of the rules matched.
  76. */
  77. public $denyCallback;
  78. /**
  79. * @var array the default configuration of access rules. Individual rule configurations
  80. * specified via [[rules]] will take precedence when the same property of the rule is configured.
  81. */
  82. public $ruleConfig = ['class' => 'yii\filters\AccessRule'];
  83. /**
  84. * @var array a list of access rule objects or configuration arrays for creating the rule objects.
  85. * If a rule is specified via a configuration array, it will be merged with [[ruleConfig]] first
  86. * before it is used for creating the rule object.
  87. * @see ruleConfig
  88. */
  89. public $rules = [];
  90. /**
  91. * Initializes the [[rules]] array by instantiating rule objects from configurations.
  92. */
  93. public function init()
  94. {
  95. parent::init();
  96. if ($this->user !== false) {
  97. $this->user = Instance::ensure($this->user, User::className());
  98. }
  99. foreach ($this->rules as $i => $rule) {
  100. if (is_array($rule)) {
  101. $this->rules[$i] = Yii::createObject(array_merge($this->ruleConfig, $rule));
  102. }
  103. }
  104. }
  105. /**
  106. * This method is invoked right before an action is to be executed (after all possible filters.)
  107. * You may override this method to do last-minute preparation for the action.
  108. * @param Action $action the action to be executed.
  109. * @return bool whether the action should continue to be executed.
  110. */
  111. public function beforeAction($action)
  112. {
  113. $user = $this->user;
  114. $request = Yii::$app->getRequest();
  115. /* @var $rule AccessRule */
  116. foreach ($this->rules as $rule) {
  117. if ($allow = $rule->allows($action, $user, $request)) {
  118. return true;
  119. } elseif ($allow === false) {
  120. if (isset($rule->denyCallback)) {
  121. call_user_func($rule->denyCallback, $rule, $action);
  122. } elseif ($this->denyCallback !== null) {
  123. call_user_func($this->denyCallback, $rule, $action);
  124. } else {
  125. $this->denyAccess($user);
  126. }
  127. return false;
  128. }
  129. }
  130. if ($this->denyCallback !== null) {
  131. call_user_func($this->denyCallback, null, $action);
  132. } else {
  133. $this->denyAccess($user);
  134. }
  135. return false;
  136. }
  137. /**
  138. * Denies the access of the user.
  139. * The default implementation will redirect the user to the login page if he is a guest;
  140. * if the user is already logged, a 403 HTTP exception will be thrown.
  141. * @param User|false $user the current user or boolean `false` in case of detached User component
  142. * @throws ForbiddenHttpException if the user is already logged in or in case of detached User component.
  143. */
  144. protected function denyAccess($user)
  145. {
  146. if ($user !== false && $user->getIsGuest()) {
  147. $user->loginRequired();
  148. } else {
  149. throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
  150. }
  151. }
  152. }