简体   繁体   English

yii2拒绝用户在后端登录

[英]yii2 deny user login on backend

I have yii2 advance template with RBAC migration applied. 我有应用RBAC迁移的yii2高级模板。 I was trying to learn RBAC and followed the Docs 2.0 . 我正在尝试学习RBAC并遵循Docs 2.0

I have logged in using database, but the front-end and back-end both get logged in with any account. 我已使用数据库登录,但前端和后端都使用任何帐户登录。 I have made 2 RBAC roles (admin, user), but can't understand or find how to 我已经做了2个RBAC角色(管理员,用户),但无法理解或找到如何

restrict back-end to login non-admin user-role. 限制后端登录非管理员用户角色。

The following is the code for roles. 以下是角色的代码。 and database entries: 和数据库条目:

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);
    }
}

User Table: 用户表:

admin   admin@gmail.com     20  10  1421197319  1421197319
user    user@gmail.com      10  10  1421198124  1421198124

Current rules: 现行规则:

'rules' => [
    [
        'actions' => ['login', 'error'],
        'allow' => true,
    ],
    [
        'actions' => ['logout', 'index'],
        'allow' => true,
        'roles' => ['@'],
    ],

Solved - Note: The solution is not exactly RBAC but ACF. 解决了 - 注意:解决方案不完全是RBAC而是ACF。

After searching and consulting, I found the solution at This yii2 viki. 经过搜索和咨询,我找到了这个yii2 viki的解决方案

I was unclear of RBAC behavior, in that I thought it won't let a role perform specific task before some action(login, submit etc). 我不清楚RBAC行为,因为我认为它不会让某个角色在某些操作(登录,提交等)之前执行特定任务。

Actually, RBAC will let you do whatever you try, and afterwards checks for permission and block if not permitted. 实际上,RBAC会让你做任何尝试,然后检查是否允许,如果不允许则阻止。

Example

There is some yard sale in a house and you are free to roam around it's front yard. 在一个房子里有一些庭院销售,你可以自由地在它的前院漫游。 The house gate/entrance doesn't have any guard at front and its not locked. 房门/入口前面没有任何防护装置,也没有锁定。 You try to sneak into the house and as soon you get into the house there is some security guard inside who abruptly stops you to identify yourself, he scan your information in the house security system(permissions in DB) and doesn't find your right to be in the house. 你试图潜入房子,一旦你进入房子,里面有一些保安人员突然阻止你识别自己,他在房屋安全系统中扫描你的信息(数据库中的权限),但找不到你的权利在家里。 He forces you out. 他强迫你出局。 This guard is RBAC 这个警卫是RBAC

I needed a guard at the front gate, who won't let anybody in unless they are allowed to. 我需要一个守卫在前门,除非他们被允许,否则他们不会让任何人进入。 And that would be ACF. 这将是ACF。

So, now I needed a way to tell the back-end system that a specific role cannot perform a specific action beforehand (ie deny non-admin login at back-end), this is not possible with RBAC so, for that we could use 'matchCallback' using ACF. 所以,现在我需要一种方法告诉后端系统特定角色不能事先执行特定操作(即拒绝后端的非管理员登录),这对RBAC是不可能的,因此我们可以使用'matchCallback'使用ACF。

Backend Rules: 后端规则:

        'rules' => [
            [
                'actions' => ['login'],
                'allow' => true,
            ],
            [
                'actions' => ['logout', 'index'],
                'allow' => true,
                'roles' => ['@'],
                'matchCallback' => function ($rule, $action) {
                    return Yii::$app->user->identity->isAdmin;
                }
            ],
         ]

The matchCallback on True allows the actions to be performed and on False denies the action. matchCallback on True允许执行操作,而False拒绝操作。 isAdmin is a getter function that needs to be defined in User model. isAdmin是一个需要在User模型中定义的getter函数。

namespace /common/models/User;

const ROLE_ADMIN = 20;
public function getIsAdmin()
{
    return $this->role == self::ROLE_ADMIN;
}

I have posted the complete working code of model in This yii2 viki's comments. 我在这个yii2 viki的评论中发布了模型的完整工作代码

You both first login user and then checking his role, there is no need for that. 你们首先登录用户然后检查他的角色,没有必要。 Your LoginForm model has getUser() method, find it after calling load() and validate() , and check role with authManager . 您的LoginForm模型具有getUser()方法,在调用load()validate()之后找到它,并使用authManager检查角色。 Smth like this: 像这样的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,
    ]);

You also don't want to validate() LoginForm twice, so add $runValidation param to the login() method. 您也不想两次validate() LoginForm,因此将$runValidation param添加到login()方法中。

public function login($runValidation = true)
{
    if ($runValidation) {

You should add behavior to you controller, like this: 您应该向控制器添加行为,如下所示:

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['create', 'delete', 'update'],
                    'allow' => true,
                    'roles' => ['admin'],
                ],
                [
                    'actions' => ['index', 'view'],
                    'allow' => true,
                    'roles' => ['user'],
                ],
            ],
        ],
    ];
}

or this EDIT: (rule so that anyone is allowed to access login but only admin is allowed to be logged in and access index page): 或者这个编辑:(规则允许任何人访问登录但只允许管理员登录并访问索引页面):

public function behaviors()
{
    return [
        'access' => [
            'class' => AccessControl::className(),
            'rules' => [
                [
                    'actions' => ['login'],
                    'allow' => true,
                    'roles' => ['?'],
                ],
                [
                    'actions' => ['index'],
                    'allow' => true,
                    'roles' => ['admin'],
                ],
            ],
        ],
    ];
}

I have achieved this functionality by changing backend login action. 我通过更改后端登录操作实现了此功能。 here is my code, i don't know, it is a perfect solution or not, but it is working for me. 这是我的代码,我不知道,它是一个完美的解决方案,但它对我有用。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM