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
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
Figure 2
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
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'))
Leave a Reply