如何在应用的模块中使用不同的authManager? [ 2.0 版本 ]
应用中的admin模块用于后台管理,admin模块的用户不同于前台的用户,admin模块配置了另外一个authManger组件。配置文件如下:
return [
'id' => 'app',
.......
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
'identityCookie' => ['name' => '_identity-app', 'httpOnly' => true],
],
'authManager' => [
......//app中的authMangager配置
],
'errorHandler' => [
'errorAction' => 'site/error',
],
],
'modules' => [
'admin' => [
'class' => 'mp\modules\admin\Module',
'aliases' => [
'@module' => '@app/modules/admin',
],
'defaultRoute' => 'site',
'components' => [
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'common\models\Staff',
'idParam' => '__admin_id',
'enableAutoLogin' => false,
'loginUrl' => '/admin/site/login',
],
'errorHandler' => [
'class' => 'yii\web\ErrorHandler',
'errorAction' => '/admin/site/error',
],
'authManager' => [
'class' => 'yii\rbac\DbManager',
......//admin模块中的authManager配置
],
],
],
],
'params' => $params,
];`
这样配置后,在admin模块检验权限的时候,还是使用了app层配置的那个authManager,怎样才能让admin模块中的代码使用模块自己的authManager呢?
同样的,errorhandler也有一样的问题,该如何解决
@drodata 的方法是可行的。也找到了其他方法可以不用再模块中替换应用的组件。
研究了一下源代码发现AccessControl在调用User组件的can方法时,如果user组件的$accessChecker属性,如果为空就使用应用的authManager组件,因此,只要设置user组件的这个属性就可以了。于是配置代码改成:
`
'modules' => [
'admin' => [
'class' => 'mp\modules\admin\Module',
'aliases' => [
'@module' => '@app/modules/admin',
],
'defaultRoute' => 'site',
'components' => [
'user' => [
'class' => 'yii\web\User',
'identityClass' => 'common\models\Staff',
'idParam' => '__admin_id',
'enableAutoLogin' => false,
'loginUrl' => '/admin/site/login',
'accessChecker' => 'yii\rbac\DbManager',
],
'errorHandler' => [
'class' => 'yii\web\ErrorHandler',
'errorAction' => '/admin/site/error',
],
],
],
],
这样修改后就可以工作了,但是存在一个问题是accessChecker的配置只能通过字符串类名初始化一个默认的组件。问题出在User组件init时是判断is_string才使用Yii::createObject方法创建accessChecker属性的,如果需要让这个属性支持配置数组。需要修改User组件的init方法代码如下:
// if (!empty($this->accessChecker) && is_string($this->accessChecker)) {
if (!empty($this->accessChecker) && (is_string($this->accessChecker) || is_array($this->accessChecker)) {
$this->accessChecker = Yii::createObject($this->accessChecker);
}
或者更进一步,改成这种形式,除了支持通过类名配置和数组配置外还能引用其他已经定义的组件。
if (!empty($this->accessChecker)) {
$this->accessChecker = Instance::ensure($this->accessChecker, BaseManager::className());
}
// if (!empty($this->accessChecker) && is_string($this->accessChecker)) {
// $this->accessChecker = Yii::createObject($this->accessChecker);
// }
`
不过很遗憾这个办法只能支持引用应用的组件而不能引用自己模块的组件。
共 4 个回答
-
按照你上面的配置,应用内会出现两个 authManager 实例:一个在应用内,通过
Yii::$app->authManager
可访问;另一个在 admin 模块内,通过Yii::$app->admin->authManager
可访问。通常用来判断权限的Yii::$app->user->can()
方法使用的是第一个 authManager.若想在 admin 模块内指定使用 admin 模块内的 authManager, 需要在模块内的 init() 内将应用内的 authManager 替换掉,例如:
// in admin Module public function init() { parent::init(); \Yii::$app->set('authManager', $this->get('authManager')); }
error handler 不工作的原因和 authManager 类似,但稍微有些不同,具体可参考: https://www.yiiframework.com/forum/index.php/topic/74234-how-to-load-an-errorhandler-in-a-module/
-
但是存在一个问题是accessChecker的配置只能通过字符串类名初始化一个默认的组件。
...
不过很遗憾这个办法只能支持引用应用的组件而不能引用自己模块的组件。
yii\web\User::accessChecker 的类型是 yii\rbac\CheckAccessInterface, 如果你想通过配置 accessChecker 的办法实现,直接将其值设置成 admin 模块的 authManager 即可:
'user' => [ 'accessChecker' => Yii::$app->admin->authManager, ],
wuyan
最后登录:2018-09-25
在线时长:1小时49分
- 粉丝0
- 金钱15
- 威望0
- 积分25