AccessControl.php 4.4 KB

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