In Yii2, you need to determine whether the current logged in user has specific interface access rights (based on RBAC, default role)

下一步不计划手动指定用户的角色,而是基于默认角色,自动指定。
1. The current permission judgment is implemented in the controller method as follows



$conventionId = $this->request->post('convention_id', '');

$convention = Convention::find()->where([
	'id' => $conventionId
])->limit(1)->one();
if (!$convention) {
	return [
		'code' => 10403,
		'message' => '大会不存在!',
	];
}

$mapping = CompanyEmployeeMapping::find()->where([
	'user_id' => Yii::$app->user->id,
	'company_id' => $convention->company_id,
])->limit(1)->one();
if (!$mapping) {
	//判断是否为联络员
	$contact = ConventionContact::find()->where('convention_id = :conventionId AND (user_id = :userId OR phone = :phone)', [
		':conventionId' => $conventionId,
		':userId' => Yii::$app->user->id,
		':phone' => Yii::$app->user->identity->pure_phone_number,
	])->limit(1)->one();
	//判断是否为签到管理员
	$checkinManager = ConventionCheckinManager::find()->where('convention_id = :conventionId AND (user_id = :userId OR phone = :phone)', [
		':conventionId' => $conventionId,
		':userId' => Yii::$app->user->id,
		':phone' => Yii::$app->user->identity->pure_phone_number,
	])->limit(1)->one();
	if (!$contact && !$checkinManager) {
		return [
			'code' => 10001,
			'message' => '您没有数据权限',
		];
	}
}




SELECT * FROM `conventions` WHERE `id`='1826937119386051' LIMIT 1

SELECT * FROM `company_employee_mapping` WHERE (`user_id`='1826937119386043') AND (`company_id`='1826937119386040') LIMIT 1

SELECT * FROM `convention_contacts` WHERE convention_id = '1826937119386051' AND (user_id = '1826937119386043' OR phone = '13980074657') LIMIT 1

SELECT * FROM `convention_checkin_managers` WHERE convention_id = '1826937119386051' AND (user_id = '1826937119386043' OR phone = '13980074657') LIMIT 1


2. The plan is implemented based on RBAC, avoiding repeated duplication in each controller method (even if a common method is extracted, it is not flexible enough) 3. Create a custom rule class Create the following rule classes in the common/rbac/ directory: CompanyEmployeeRule.php


<?php

namespace commonrbac;

use yiirbacItem;
use yiirbacRule;
use commonmodelsCompanyEmployeeMapping;

/**
 * 检查 user_id 是否和通过参数传进来的 user 参数相符
 */
class CompanyEmployeeRule extends Rule
{
    public $name = 'isCompanyEmployee';

    /**
     * @param string|integer $user 用户 ID.
     * @param Item $item 该规则相关的角色或者权限
     * @param array $params 传给 ManagerInterface::checkAccess() 的参数
     * @return boolean 代表该规则相关的角色或者权限是否被允许
     */
    public function execute($user, $item, $params): bool
    {
        if (!isset($params['convention'])) {
            return false;
        }

        return CompanyEmployeeMapping::find()
            ->where([
                'user_id' => $user,
                'company_id' => $params['convention']->company_id,
            ])
            ->exists();
    }
}


ConventionContactRule.php


<?php

namespace commonrbac;

use commonmodelsUser;
use yiirbacItem;
use yiirbacRule;
use commonmodelsConventionContact;

/**
 * 检查 user_id 是否和通过参数传进来的 user 参数相符
 */
class ConventionContactRule extends Rule
{
    public $name = 'isConventionContact';

    /**
     * @param string|integer $user 用户 ID.
     * @param Item $item 该规则相关的角色或者权限
     * @param array $params 传给 ManagerInterface::checkAccess() 的参数
     * @return boolean 代表该规则相关的角色或者权限是否被允许
     */
    public function execute($user, $item, $params): bool
    {
        if (!isset($params['convention'])) {
            return false;
        }

        $userModel = User::findOne($user);

        return ConventionContact::find()
            ->where([
                'convention_id' => $params['convention']->id,
                'user_id' => $user,
                'phone' => $userModel->pure_phone_number,
            ])->exists();
    }
}


CheckinManagerRule.php


<?php

namespace commonrbac;

use commonmodelsUser;
use yiirbacItem;
use yiirbacRule;
use commonmodelsConventionCheckinManager;

/**
 * 检查 user_id 是否和通过参数传进来的 user 参数相符
 */
class CheckinManagerRule extends Rule
{
    public $name = 'isCompanyEmployee';

    /**
     * @param string|integer $user 用户 ID.
     * @param Item $item 该规则相关的角色或者权限
     * @param array $params 传给 ManagerInterface::checkAccess() 的参数
     * @return boolean 代表该规则相关的角色或者权限是否被允许
     */
    public function execute($user, $item, $params): bool
    {
        if (!isset($params['convention'])) {
            return false;
        }

        $userModel = User::findOne($user);

        return ConventionCheckinManager::find()
            ->where([
                'convention_id' => $params['convention']->id,
                'user_id' => $user,
                'phone' => $userModel->pure_phone_number,
            ])->exists();
    }
}


4. The so-called default role is the role assigned to all users implicitly. There is no need to call the yiirbacmanagerInterface::assign() method for display assignment, and the authorization data does not contain the assignment information. Create a new migration with ./yii migrate/create init_convention_rbac and then implement the creation hierarchy


<?php

use yiidbMigration;
use commonrbacCompanyEmployeeRule;
use commonrbacConventionContactRule;
use commonrbacCheckinManagerRule;
use yiibaseException;

/**
 * Class m250331_034538_init_convention_rbac
 */
class m250331_034538_init_convention_rbac extends Migration
{
    /**
     * @return void
     * @throws Exception
     */
    public function safeUp()
    {
        $auth = Yii::$app->authManager;

        // 清除所有现有RBAC数据
        $auth->removeAll();
        
        // 创建自定义规则
        $companyEmployeeRule = new CompanyEmployeeRule();
        $auth->add($companyEmployeeRule);

        $conventionContactRule = new ConventionContactRule();
        $auth->add($conventionContactRule);

        $checkinManagerRule = new CheckinManagerRule();
        $auth->add($checkinManagerRule);

        // 创建权限
        $accessConvention = $auth->createPermission('accessConvention');
        $accessConvention->description = '访问大会数据权限';
        $auth->add($accessConvention);

        // 创建角色并分配规则
        $companyEmployee = $auth->createRole('companyEmployee');
        $companyEmployee->ruleName = $companyEmployeeRule->name;
        $auth->add($companyEmployee);
        $auth->addChild($companyEmployee, $accessConvention);

        $conventionContact = $auth->createRole('conventionContact');
        $conventionContact->ruleName = $conventionContactRule->name;
        $auth->add($conventionContact);
        $auth->addChild($conventionContact, $accessConvention);

        $checkinManager = $auth->createRole('checkinManager');
        $checkinManager->ruleName = $checkinManagerRule->name;
        $auth->add($checkinManager);
        $auth->addChild($checkinManager, $accessConvention);
    }

    /**
     * {@inheritdoc}
     */
    public function safeDown()
    {
        echo "m250331_034538_init_convention_rbac cannot be reverted.n";

        return false;
    }

    /*
    // Use up()/down() to run migration code without a transaction.
    public function up()
    {

    }

    public function down()
    {
        echo "m250331_034538_init_convention_rbac cannot be reverted.n";

        return false;
    }
    */
}



5. Now there are 3 roles: CompanyEmployee, ConventionContact, and CheckInManager, all have permissions to AccessConvention. And the rule to check if a user satisfies the role has been defined. 6. The next step is not to manually specify the user’s role, but automatically assign based on the default role. Reference: Use the default role https://www.yiiframework.com/doc/guide/2.0/en-en/security-authorization#using-default-roles Specify the yiirbacbasemanager::$defaultroles option when configuring AuthManager. as shown in Figure 1
下一步不计划手动指定用户的角色,而是基于默认角色,自动指定。
Figure 1


return [
    // ...
    'components' => [
        'authManager' => [
            'class' => 'yiirbacDbManager',
            // 'cache' => 'cache',
            'defaultRoles' => ['companyEmployee', 'conventionContact', 'checkinManager'],
        ],
        // ...
    ],
];


  7. Check whether the current user has AccessConvention permissions. Confirmation check passed, with AccessConvention permission. carrycan()Methods check roles and permissions. The user has a role or its inherited role, in line with expectations. as shown in Figure 2
检查当前用户是否具有 accessConvention 权限。确认检查通过,具有 accessConvention 权限。通过 'can()' 方法会检查角色和权限。用户拥有角色或其继承角色,符合预期
Figure 2


        if (Yii::$app->user->can('accessConvention', ['convention' => $convention])) {
            $roles = Yii::$app->authManager->getRolesByUser(Yii::$app->user->id);
            print_r($roles);
        }
        if (Yii::$app->user->can('companyEmployee', ['convention' => $convention])) {  // 'can()' 方法会检查角色和权限
            echo '用户拥有 'companyEmployee' 角色或其继承角色';
        }
        if (Yii::$app->user->can('conventionContact', ['convention' => $convention])) {  // 'can()' 方法会检查角色和权限
            echo '用户拥有 'conventionContact' 角色或其继承角色';
        }
        if (Yii::$app->user->can('checkinManager', ['convention' => $convention])) {  // 'can()' 方法会检查角色和权限
            echo '用户拥有 'checkinManager' 角色或其继承角色';
        }




SELECT * FROM `auth_assignment` WHERE `user_id`='1826937119386043'

SELECT * FROM `auth_item` WHERE `name`='accessConvention'

SELECT `parent` FROM `auth_item_child` WHERE `child`='accessConvention'

SELECT * FROM `auth_item` WHERE `name`='checkinManager'

SELECT `data` FROM `auth_rule` WHERE `name`='isCheckinManager'

SELECT * FROM `users` WHERE `id`='1826937119386043'

SELECT EXISTS(SELECT * FROM `convention_checkin_managers` WHERE (`convention_id`='1826937119386051') AND (`user_id`='1826937119386043') AND (`phone`='13980074657'))

SELECT * FROM `auth_item` WHERE `name`='companyEmployee'

SELECT `data` FROM `auth_rule` WHERE `name`='isCompanyEmployee'

SELECT EXISTS(SELECT * FROM `company_employee_mapping` WHERE (`user_id`='1826937119386043') AND (`company_id`='1826937119386040'))

SELECT `b`.* FROM `auth_assignment` `a`, `auth_item` `b` WHERE (`a`.`item_name`=`b`.`name`) AND (`a`.`user_id`='1826937119386043') AND (`b`.`type`=1)


  8. Check whether the current user has AccessConvention permissions. Confirm that the check does not pass, and there is no output. Does not have AccessConvention permissions. carrycan()Methods check roles and permissions. The user has a role or its inherited role, in line with expectations. as shown in Figure 3
检查当前用户是否具有 accessConvention 权限。确认检查不通过,无任何输出。不具有 accessConvention 权限。通过 'can()' 方法会检查角色和权限。用户拥有角色或其继承角色,符合预期
Figure 3


SELECT * FROM `auth_assignment` WHERE `user_id`='1827082629726231'

SELECT * FROM `users` WHERE `id`='1827082629726231'

SELECT EXISTS(SELECT * FROM `convention_checkin_managers` WHERE (`convention_id`='1826937119386051') AND (`user_id`='1827082629726231') AND (`phone`='15609979522'))

SELECT EXISTS(SELECT * FROM `company_employee_mapping` WHERE (`user_id`='1827082629726231') AND (`company_id`='1826937119386040'))

SELECT * FROM `users` WHERE `id`='1827082629726231'

SELECT EXISTS(SELECT * FROM `convention_contacts` WHERE (`convention_id`='1826937119386051') AND (`user_id`='1827082629726231') AND (`phone`='15609979522'))

SELECT EXISTS(SELECT * FROM `company_employee_mapping` WHERE (`user_id`='1827082629726231') AND (`company_id`='1826937119386040'))

SELECT * FROM `users` WHERE `id`='1827082629726231'

SELECT EXISTS(SELECT * FROM `convention_contacts` WHERE (`convention_id`='1826937119386051') AND (`user_id`='1827082629726231') AND (`phone`='15609979522'))

SELECT * FROM `users` WHERE `id`='1827082629726231'

SELECT EXISTS(SELECT * FROM `convention_checkin_managers` WHERE (`convention_id`='1826937119386051') AND (`user_id`='1827082629726231') AND (`phone`='15609979522'))


   

Comments

One response to “In Yii2, you need to determine whether the current logged in user has specific interface access rights (based on RBAC, default role)”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.