diff --git a/README.md b/README.md index f4381e2..345a79e 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,6 @@ php yii migrate --migrationPath=@yii/rbac/migrations/ ], 'as access' => [ 'class' => 'yiier\rbac\components\AccessControl', - // 'allowActions' => ['site/login', 'site/error', 'site/captcha', 'order/*'] //白名单 ], ``` @@ -108,6 +107,7 @@ php yii migrate --migrationPath=@yii/rbac/migrations/ 'yiier.rbac.config' => [ 'cacheDuration' => 3600, // 缓存时间,默认是 30 天,单位是秒 'superManId' => 12 //拥有所有权限 + 'freeAccessRoutes' => ['/site/login', '/site/error', '/site/captcha', '/order/*'], // 白名单 URL ] ``` diff --git a/src/components/AccessControl.php b/src/components/AccessControl.php index 3c92362..0454878 100644 --- a/src/components/AccessControl.php +++ b/src/components/AccessControl.php @@ -3,7 +3,6 @@ namespace yiier\rbac\components; use Yii; -use yii\base\Module; use yii\di\Instance; use yii\web\ForbiddenHttpException; use yii\web\User; @@ -20,7 +19,6 @@ * ``` * 'as access' => [ * 'class' => 'yiier\rbac\components\AccessControl', - * 'allowActions' => ['site/login', 'site/error', 'site/captcha', order/*] * ] * ``` * @@ -71,7 +69,7 @@ public function setUser($user) public function beforeAction($action) { $user = $this->getUser(); - if ((!$user->getIsGuest()) && AuthHelper::canRoute(Yii::$app->getRequest()->url, $user)) { + if ((!$user->getIsGuest()) && AuthHelper::canRoute(Yii::$app->getRequest()->url, $user, $action)) { return true; } $this->denyAccess($user); @@ -116,37 +114,6 @@ protected function isActive($action) return false; } } - - - if ($this->owner instanceof Module) { - // convert action uniqueId into an ID relative to the module - $mid = $this->owner->getUniqueId(); - $id = $uniqueId; - if ($mid !== '' && strpos($id, $mid . '/') === 0) { - $id = substr($id, strlen($mid) + 1); - } - } else { - $id = $action->id; - } - foreach ($this->allowActions as $route) { - if (substr($route, -1) === '*') { - $route = rtrim($route, "*"); - if ($route === '' || strpos($id, $route) === 0) { - return false; - } - } else { - if ($id === $route) { - return false; - } - } - } - - if ( - $action->controller->hasMethod('allowAction') - && in_array($action->id, $action->controller->allowAction()) - ) { - return false; - } return true; } } \ No newline at end of file diff --git a/src/helpers/AuthHelper.php b/src/helpers/AuthHelper.php index 792bca3..281bdd3 100644 --- a/src/helpers/AuthHelper.php +++ b/src/helpers/AuthHelper.php @@ -9,6 +9,7 @@ use Yii; +use yii\base\Action; use yii\caching\TagDependency; use yii\helpers\Url; use yii\web\User; @@ -21,10 +22,11 @@ class AuthHelper /** * @param $route * @param User|null $user + * @param Action|null $action * @return bool * @throws \yii\base\InvalidConfigException */ - public static function canRoute($route, User $user = null) + public static function canRoute($route, User $user = null, $action = null) { $userId = $user ? $user->getId() : Yii::$app->getUser()->getId(); if ($userId == Config::instance()->superManId) { @@ -35,10 +37,61 @@ public static function canRoute($route, User $user = null) if (substr($baseRoute, 0, 4) === "http") { return true; } + + if (self::isFreeAccess($baseRoute, $action)) { + return true; + } + $routesByUser = static::getRoutesByUser($userId); return self::isRouteAllowed($baseRoute, $routesByUser); } + /** + * CCheck if controller has $freeAccess = true or $action in $freeAccessActions + * Or it's login, logout, error page + * + * @param string $route + * @param Action|null $action + * + * @return bool + * @throws \yii\base\InvalidConfigException + */ + private static function isFreeAccess($route, $action = null) + { + if ($action) { + $controller = $action->controller; + if ($controller->hasProperty('freeAccess') AND $controller->freeAccess === true) { + return true; + } + if ($controller->hasProperty('freeAccessRoutes') AND in_array($action->id, $controller->freeAccessRoutes)) { + return true; + } + } + $systemPages = [ + '/site/logout', + AuthHelper::unifyRoute(Yii::$app->errorHandler->errorAction), + AuthHelper::unifyRoute(Yii::$app->user->loginUrl), + ]; + if (in_array($route, $systemPages)) { + return true; + } + // if config freeAccessRoutes parameter + foreach (Config::instance()->freeAccessRoutes as $freeAccessRoute) { + if (substr($freeAccessRoute, -1) === '*') { + $freeAccessRoute = rtrim($freeAccessRoute, "*"); + if ($freeAccessRoute === '' || strpos($route, $freeAccessRoute) === 0) { + return true; + } + } else { + if ($freeAccessRoute === $route) { + return true; + } + } + } + return false; + } + + /** * @return array * @throws \yii\base\InvalidConfigException diff --git a/src/helpers/Config.php b/src/helpers/Config.php index cb60dd8..ca65cb0 100644 --- a/src/helpers/Config.php +++ b/src/helpers/Config.php @@ -11,6 +11,17 @@ use Yii; use yii\helpers\ArrayHelper; +/** + * Class Config + * + * 'yiier.rbac.config' => [ + * 'cacheDuration' => 3600, + * 'freeAccessRoutes' => ['/site/login', '/site/error', '/site/captcha', '/order/*'], + * 'superManId' => 12 + * ] + * + * @package yiier\rbac\helpers + */ class Config { const CACHE_TAG = 'yiier.rbac'; @@ -18,6 +29,7 @@ class Config public $menus = []; public $superManId; + public $freeAccessRoutes = []; public $cacheDuration = 3600 * 30; // default 30 day /** diff --git a/src/widgets/SuperMenu.php b/src/widgets/SuperMenu.php index e00abec..ec89083 100644 --- a/src/widgets/SuperMenu.php +++ b/src/widgets/SuperMenu.php @@ -177,7 +177,6 @@ protected function normalizeItems($items, &$active) $active = true; } } -// pr($items, 0); return array_values($items); } @@ -200,21 +199,15 @@ protected function isItemActive($item) } $route = ltrim($route, '/'); - if (isset($item['strict']) && $item['strict'] === true) { + $arrayRoute = explode('/', $route); + $routeCount = count($arrayRoute); + if ((isset($item['strict']) && $item['strict'] === true) || $routeCount == 2) { if ($route != $this->route && $route !== $this->noDefaultRoute && $route !== $this->noDefaultAction) { return false; } } else { - $arrayRoute = explode('/', $route); $arrayThisRoute = explode('/', $this->route); - - //改写了路由的规则,是否高亮判断到controller而非action - $routeCount = count($arrayRoute); - if ($routeCount == 2) { - if ($arrayRoute[0] !== $arrayThisRoute[0]) { - return false; - } - } elseif ($routeCount == 3) { + if ($routeCount == 3) { if ($arrayRoute[0] !== $arrayThisRoute[0]) { return false; }