مفاهیم پایه
Role Based Access Control یا به طور خلاصه RBAC یک سیستم مدیریت دسترسی هاست که در yii2 گنجانده شده. هر نقش(role) در RBAC شامل مجموعه ای از مجوز هاست یک نقش میتونه به یک یا چند کاربر اختصاص داده بشه. به عنوان مثال نقش manage user(مدیریت کاربران) میتونه شامل مجوز های add user, edit user و delete user باشه. به منظور کنترل سطح دسترسی باید مشخص بشه آیا به کاربر جاری نقش یا مجوز لازم اختصاص داده شده یا خیر.
نقش ها و یا مجوز ها میتونن سازمان یافته و سلسله مراتبی باشن یعنی یک نقش میتونه شامل نقش های دیگه ای باشه، مجوز ها هم همینطور.
به عنوان مثال فرض کنید یک سیستم مدیریت مقالات داریم. کاربران این سیستم شامل سه گروه میشن:
- کاربران عادی که میتونن مقالات رو بخونن یا مقاله ارسال کنن.
- ناظم هایی که میتونن مقالات ارسال شده توسط گروه اول رو ویرایش، تایید و یا حذف کنن.
- مدیرانی که میتونن هر کاری انجام بدن از جمله مدیریت کاربران و...
در این مثال برای گروه اول نیازی نیست سطح دسترسی تعریف کنیم و یا اینکه مجوزی مورد بررسی قرار بگیره! چون تمام کاربران باید بتونن مقالات رو بخونن و یا مقاله ارسال کنن.
برای گروه دوم میشه یک نقش تعریف کرد با عنوان managing articles و برای گروه سوم هم که قراره کاربران رو مدیریت کنن نقش managing users رو داریم. نقش ها و مجوز ها باید به صورت سلسله مراتبی تعریف بشن چون گروه سوم یا مدیران ما علاوه بر مدیریت کاربران باید بتونن مقالات رو هم ویرایش، تایید و یا حذف کنن یعنی نقش های گروه دوم رو هم باید داشته باشن پس طرح سلسله مراتبی ما چیزی مثل تصویر زیر خواهد شد:
پیاده سازی
قبل از اینکه پیاده سازی رو انجام بدیم باید authManager رو پیکره بندی کنیم. برای پیکره بندی authManager دو روش وجود داره. استفاده از PhpManager و یا DbManager. اگر از روش اول استفاده کنید باید تمام اطلاعات مربوط به سطح دسترسی های کاربرانُ در یک یک فایل php قرار بدین. این روش معمولا برای زمانی هست که نقش ها ثابت هستن و نیازی به مدیریت مجوز ها ندارید.
در روش دوم، اطلاعات مربوط به دسترسی ها داخل پایگاه داده ذخیره میشه. امکان مدیریت پویا به آسانی فراهم شده و همچنین وضوح بیشتری نسبت به روش اول داره. برای استفاده از این روش پیکره بندی زیرُ انجام میدیم(common/config/main.php)
return [
// ...
'components' => [
'authManager' => [
'class' => 'yii\rbac\DbManager',
],
// ...
],
];
حالا برای مقداردهی اولیه rbac از migrations استفاده میکنیم.
./yii migrate --migrationPath=@yii/rbac/migrations
برای DbManager داخل پایگاه داده 4 جدول ساخته میشه:
- auth_item: جدول مربوط به ذخیره سازی مجوز ها(مجوز ها در این جدول نگهداری میشوند).
- auth_item_child: مربوط به سلسله مراتب مجوز هاست، مشخص کننده ارتباط پدر و فرزندی مجوز ها.
- auth_assignment: مشخص میکند کدام مجوز به کدام کاربر اختصاص داده شده.
- auth_rule: جدول نگهداری قوانین.
برای مقدار دهی اولیه و همیچنین تغییر مجوز و نقش ها باز هم از migrations استفاده کنیم.
./yii migrate/create init_rbac
اگر دستور شما با موفقیت اجرا شده باشه باید در قسمت migration هاتون یک فایل با نامی مثل m141204_121823_init_rbac داشته باشید. بازش کنید چون تصمیم داریم قبل از up کردنش نقش ها و مجوز هامون رو داخلش تعریف کنیم.
class m141204_121823_init_rbac extends Migration
{
public function up()
{
$auth = Yii::$app->authManager;
$manageArticles = $auth->createPermission('manageArticles');
$manageArticles->description = 'Manage articles';
$auth->add($manageArticles);
$manageUsers = $auth->createPermission('manageUsers');
$manageUsers->description = 'Manage users';
$auth->add($manageUsers);
$moderator = $auth->createRole('moderator');
$moderator->description = 'Moderator';
$auth->add($moderator);
$auth->addChild($moderator, $manageArticles);
$admin = $auth->createRole('admin');
$admin->description = 'Administrator';
$auth->add($admin);
$auth->addChild($admin, $moderator);
$auth->addChild($admin, $manageUsers);
}
public function down()
{
Yii::$app->authManager->removeAll();
}
}
در کد بالا توسط دو متد createPermission و createRole مجوز و نقش ها رو تعریف کردیم. در پراپرتی description میتونید توضیح کوتاهی در مورد نقش یا مجوزتون قرار بدین با add باید اونها رو به authManager اضافه کنید و با استفاده از متد addChild یک مجوز رو به یک نقش اختصاص بدین(برای تمام مجوز ها باید این کارُ انجام بدین).
از متد assign برای اختصاص دادن مجوز ها به کاربران استفاده میشه در همین migrate میتونید به روش زیر ازش استفاده کنید
$auth->assign($moderator, 2); // user id 2$auth->assign($admin, 1); // user id 1
نقش ناظم به کاربر با شناسه 2 و نقش مدیر به کاربر با شناسه 1 اختصاص داده شد.
یا اینکه هنگام ثبت کاربر جدید به صورت زیر عمل کنید
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
$user->save(false); // the following three lines were added:
$auth = \Yii::$app->authManager;
$authorRole = $auth->getRole('author');
$auth->assign($authorRole, $user->getId());
return $user;
}
return null;
}
برای فهم بهتر این موضوع migration رو up و سری به 4 جدول ذکر شده بزنید.
اطلاعات مربوط به دسترسی ها آماده شده و برای بررسی اینکه آیا کاربر مجوز مورد نظر شما رو داره یا نه میتونید به راحتی از متد can استفاده کنید.
if (\Yii::$app->user->can('manageArticles')) {
// create post
}
یا اینکه میتونید داخل behaviors ها به صورت زیر تعریفش کنید.
namespace app\controllers;
use yii\web\Controller;
use yii\filters\AccessControl;
class ArticleController extends Controller
{
public function behaviors()
{
return [
'access' => ['
'class' => AccessControl::className(),
'only' => ['suggest', 'queue', 'delete', 'update'], //only be applied to
'rules' => [
[
'allow' => true, 'actions' => ['suggest', 'update'],
'roles' => ['@'],
],
[
'allow' => true,
'actions' => ['queue', 'delete'],
'roles' => ['manageArticles'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => ['delete' => ['post'],
],
],
];
}
// ...
موضوع به اینجا ختم نمیشه، یک سیستم مدیریت محتوا با چندین نویسنده رو فرض کنید. ممکنه بخواهید نویسنده ها تنها مطالبی رو بتونن ویرایش کنن که خودشون اونها رو ایجاد کردن یا به عبارت دیگه مالک اون باشن. شاید استفاده از دستور شرطی زیر اینجا کارتونُ راه بندازه اما همیشه اینطور نخواهد بود.
if (\Yii::$app->user->can('updatePost') && $postModel->owner == Yii::$app->user->identity) {
// update post
}
برای مدیریت این دسترسی ها از قوانین و جدول شماره 4، جدول نگهداری قوانین استفاده میکنیم که بعدا به طور جدا در موردش خواهم نوشت.
rbac