yii2拒绝用户在后端登录

时间:2015-01-14 02:56:48

标签: php yii2 rbac

我有应用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' => ['@'],
    ],

4 个答案:

答案 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;
}

我已在This yii2 viki's comments.

中发布了完整的模型工作代码

答案 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,
        ]);
    }
}