我有应用RBAC迁移的yii2高级模板。我试图学习RBAC并遵循Docs 2.0。
我已使用数据库登录,但前端和后端都使用任何帐户登录。我已经做了2个RBAC角色(管理员,用户),但无法理解或找到如何
将后端限制为登录非管理员用户角色。
以下是角色的代码。和数据库条目:
namespace console\controllers;
use Yii;
use yii\console\Controller;
class RbacController extends Controller
{
public function actionInit()
{
$auth = Yii::$app->authManager;
// add "admin" role
$admin = $auth->createRole('admin');
$auth->add($admin);
// add "user" role
$user = $auth->createRole('user');
$auth->add($user);
$auth->assign($admin, 1);
}
}
用户表:
admin admin@gmail.com 20 10 1421197319 1421197319
user user@gmail.com 10 10 1421198124 1421198124
现行规则:
'rules' => [
[
'actions' => ['login', 'error'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['@'],
],
答案 0 :(得分:11)
已解决 - 注意:解决方案不完全是RBAC而是ACF。
在搜索和咨询后,我在This yii2 viki.
找到了解决方案我不清楚RBAC的行为,因为我认为它不会让一个角色 在执行某些操作(登录,提交等)之前执行特定任务。
实际上,RBAC会让你做任何尝试,然后检查 如果不允许则允许和阻止。
示例强>
在房子里有一些庭院出售,你可以自由地漫游 在它的前院附近。房门/入口没有任何警卫 在前面,它没有锁定。你试图偷偷溜进房子里 很快你进入房子里面有一些保安人员 突然停止你识别自己,他扫描你的信息 房屋安全系统(DB中的权限)并没有找到你的 在房子里的权利。他强迫你出局。这名后卫是RBAC
我在前门需要一名后卫,他除非获胜,否则不会让任何人进入 他们被允许。这将是ACF。
所以,现在我需要一种方法告诉后端系统一个特定的 角色无法事先执行特定操作(即拒绝非管理员) 在后端登录),这对RBAC来说是不可能的,为此我们 可以使用' matchCallback'使用ACF。
后端规则:
'rules' => [
[
'actions' => ['login'],
'allow' => true,
],
[
'actions' => ['logout', 'index'],
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return Yii::$app->user->identity->isAdmin;
}
],
]
matchCallback
on True允许执行操作,而False拒绝操作。 isAdmin
是一个需要在User
模型中定义的getter函数。
namespace /common/models/User;
const ROLE_ADMIN = 20;
public function getIsAdmin()
{
return $this->role == self::ROLE_ADMIN;
}
中发布了完整的模型工作代码
答案 1 :(得分:2)
您首先登录用户然后检查他的角色,没有必要。
您的LoginForm模型具有getUser()
方法,在调用load()
和validate()
后找到它,并使用authManager
检查角色。像这样的Smth:
/** @var LoginForm $model */
$model = Yii::createObject('loginForm');
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
/** @var User $user */
$user = $model->getUser();
if (!empty($user) && Yii::$app->authManager->checkAccess($user->getId(), 'admin')) {
// Don't validate twice
$model->login(false);
return $this->goBack();
} else {
$model->addError('email', 'This user is not authorized for administration');
}
}
return $this->render('login.twig', [
'model' => $model,
]);
您也不想validate()
两次使用LoginForm,因此请将$runValidation
param添加到login()
方法中。
public function login($runValidation = true)
{
if ($runValidation) {
答案 2 :(得分:0)
您应该向控制器添加行为,如下所示:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['create', 'delete', 'update'],
'allow' => true,
'roles' => ['admin'],
],
[
'actions' => ['index', 'view'],
'allow' => true,
'roles' => ['user'],
],
],
],
];
}
或编辑:(规则允许任何人访问登录但只允许管理员登录并访问索引页):
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['login'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['index'],
'allow' => true,
'roles' => ['admin'],
],
],
],
];
}
答案 3 :(得分:0)
我通过更改后端登录操作实现了此功能。 这是我的代码,我不知道,这是一个完美的解决方案,但它对我有用。
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
//check user roles, is user is Admin?
if (\Yii::$app->user->can('Admin'))
{
// yes he is Admin, so redirect page
return $this->goBack();
}
else // if he is not an Admin then what :P
{ // put him out :P Automatically logout.
Yii::$app->user->logout();
// set error on login page.
\Yii::$app->getSession()->setFlash('error', 'You are not authorized to login Admin\'s penal.<br /> Please use valid Username & Password.<br />Please contact Administrator for details.');
//redirect again page to login form.
return $this->redirect(['site/login']);
}
} else {
return $this->render('login', [
'model' => $model,
]);
}
}