AccessControl.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. <?php
  2. /**
  3. * Author: lf
  4. * Blog: https://blog.feehi.com
  5. * Email: job@feehi.com
  6. * Created at: 2017-09-10 16:42
  7. */
  8. namespace backend\components;
  9. use Yii;
  10. use yii\web\ForbiddenHttpException;
  11. use yii\base\Module;
  12. use yii\web\User;
  13. use yii\di\Instance;
  14. class AccessControl extends \yii\base\ActionFilter
  15. {
  16. /* @var User */
  17. private $_user = 'user';
  18. public $allowActions = [];
  19. public $superAdminUserIds = [];
  20. /**
  21. * Get user
  22. * @return User
  23. * @throws \yii\base\InvalidConfigException
  24. */
  25. public function getUser()
  26. {
  27. if (!$this->_user instanceof User) {
  28. $this->_user = Instance::ensure($this->_user, User::className());
  29. }
  30. return $this->_user;
  31. }
  32. /**
  33. * Set user
  34. * @param User|string $user
  35. */
  36. public function setUser($user)
  37. {
  38. $this->_user = $user;
  39. }
  40. /**
  41. * @inheritdoc
  42. */
  43. public function beforeAction($action)
  44. {
  45. $actionId = $action->getUniqueId();
  46. $user = $this->getUser();
  47. if( in_array($user->getId(), $this->superAdminUserIds) ){
  48. return true;
  49. }
  50. if (self::checkRoute('/' . $actionId, Yii::$app->getRequest()->get(), $user)) {
  51. return true;
  52. }
  53. $this->denyAccess($user);
  54. }
  55. /**
  56. * Denies the access of the user.
  57. * The default implementation will redirect the user to the login page if he is a guest;
  58. * if the user is already logged, a 403 HTTP exception will be thrown.
  59. * @param User $user the current user
  60. * @throws ForbiddenHttpException if the user is already logged in.
  61. */
  62. protected function denyAccess($user)
  63. {
  64. if ($user->getIsGuest()) {
  65. $user->loginRequired();
  66. } else {
  67. throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
  68. }
  69. }
  70. /**
  71. * @inheritdoc
  72. */
  73. protected function isActive($action)
  74. {
  75. $uniqueId = $action->getUniqueId();
  76. if ($uniqueId === Yii::$app->getErrorHandler()->errorAction) {
  77. return false;
  78. }
  79. $user = $this->getUser();
  80. if($user->getIsGuest())
  81. {
  82. $loginUrl = null;
  83. if(is_array($user->loginUrl) && isset($user->loginUrl[0])){
  84. $loginUrl = $user->loginUrl[0];
  85. }else if(is_string($user->loginUrl)){
  86. $loginUrl = $user->loginUrl;
  87. }
  88. if(!is_null($loginUrl) && trim($loginUrl,'/') === $uniqueId)
  89. {
  90. return false;
  91. }
  92. }
  93. if ($this->owner instanceof Module) {
  94. // convert action uniqueId into an ID relative to the module
  95. $mid = $this->owner->getUniqueId();
  96. $id = $uniqueId;
  97. if ($mid !== '' && strpos($id, $mid . '/') === 0) {
  98. $id = substr($id, strlen($mid) + 1);
  99. }
  100. } else {
  101. $id = $action->id;
  102. }
  103. foreach ($this->allowActions as $route) {
  104. if (substr($route, -1) === '*') {
  105. $route = rtrim($route, "*");
  106. if ($route === '' || strpos($id, $route) === 0) {
  107. return false;
  108. }
  109. } else {
  110. if ($id === $route) {
  111. return false;
  112. }
  113. }
  114. }
  115. if ($action->controller->hasMethod('allowAction') && in_array($action->id, $action->controller->allowAction())) {
  116. return false;
  117. }
  118. return true;
  119. }
  120. /**
  121. * Check access route for user.
  122. * @param string|array $route
  123. * @param integer|User $user
  124. * @return boolean
  125. */
  126. public static function checkRoute($route, $params = [], $user = null)
  127. {
  128. $r = static::normalizeRoute($route);
  129. if ($user === null) {
  130. $user = Yii::$app->getUser();
  131. }
  132. $userId = $user instanceof User ? $user->getId() : $user;
  133. if ($user->can($r, $params)) {
  134. return true;
  135. }
  136. while (($pos = strrpos($r, '/')) > 0) {
  137. $r = substr($r, 0, $pos);
  138. if ($user->can($r . '/*', $params)) {
  139. return true;
  140. }
  141. }
  142. return $user->can('/*', $params);
  143. }
  144. protected static function normalizeRoute($route)
  145. {
  146. if ($route === '') {
  147. return '/' . Yii::$app->controller->getRoute() . ':' . yii::$app->getRequest()->getMethod();
  148. } elseif (strncmp($route, '/', 1) === 0) {
  149. return $route . ':' . yii::$app->getRequest()->getMethod();
  150. } elseif (strpos($route, '/') === false) {
  151. return '/' . Yii::$app->controller->getUniqueId() . '/' . $route . ':' . yii::$app->getRequest()->getMethod();
  152. } elseif (($mid = Yii::$app->controller->module->getUniqueId()) !== '') {
  153. return '/' . $mid . '/' . $route . ':' . yii::$app->getRequest()->getMethod();
  154. }
  155. return '/' . $route . ':' . yii::$app->getRequest()->getMethod();
  156. }
  157. }