RBAC vs ABAC؛ مدیریت دسترسی در سیستم‌های بزرگ

RBAC vs ABAC؛ مدیریت دسترسی در سیستم‌های بزرگ

توسعه‌دهنده بک‌اند

هرچه یک نرم‌افزار بزرگ‌تر می‌شود، مدیریت دسترسی کاربران نیز پیچیده‌تر می‌شود.

RBAC vs ABAC؛ مدیریت دسترسی در سیستم‌های بزرگ

صارم توکلی

۸ دقیقه مطالعه

۳ نفر

۱۴۰۵/۶/۳۰

RBAC vs ABAC مدیریت دسترسی در سیستم‌های بزرگ

هرچه یک نرم‌افزار بزرگ‌تر می‌شود، مدیریت دسترسی کاربران نیز پیچیده‌تر می‌شود.

در یک پروژه ساده شاید کافی باشد مشخص کنیم کاربر Admin است یا User. اما در یک سیستم سازمانی، فروشگاه بزرگ، SaaS یا پلتفرم چندمستاجری، موضوع به همین سادگی نیست.

ممکن است یک کاربر مدیر باشد، اما فقط به اطلاعات یک شعبه دسترسی داشته باشد. کاربر دیگری بتواند سفارش‌ها را مشاهده کند، اما فقط سفارش‌های مربوط به واحد خودش را ببیند. حتی ممکن است دسترسی یک کاربر بر اساس ساعت، موقعیت، مالکیت داده یا وضعیت یک Resource تغییر کند.

اینجاست که مدل‌های RBAC و ABAC اهمیت پیدا می‌کنند.

RBAC دسترسی را بر اساس نقش کاربر مدیریت می‌کند، در حالی که ABAC تصمیم دسترسی را بر اساس ویژگی‌های کاربر، منبع، عملیات و محیط می‌گیرد.


RBAC چیست؟

RBAC مخفف Role-Based Access Control است.

در این مدل، دسترسی مستقیماً به کاربر داده نمی‌شود؛ بلکه کاربر یک یا چند Role دارد و Roleها مشخص می‌کنند چه Permissionهایی در اختیار کاربر قرار دارد.

برای مثال:

User → Role → Permission

فرض کنید یک سیستم فروشگاهی داشته باشیم.

Roleها می‌توانند شامل موارد زیر باشند:

  • Admin

  • Manager

  • Seller

  • Support

  • Customer

و Permissionها:

  • product.read

  • product.create

  • product.update

  • order.read

  • order.update

  • user.manage

در این حالت می‌توان تعریف کرد:

Admin

به تمام Permissionها دسترسی دارد.

Seller

به مدیریت محصولات و مشاهده سفارش‌ها دسترسی دارد.

Support

می‌تواند سفارش‌ها و تیکت‌ها را مشاهده کند.

Customer

فقط می‌تواند اطلاعات و سفارش‌های خودش را مشاهده کند.

این ساختار ساده، قابل فهم و نسبتاً قابل مدیریت است.


مزیت اصلی RBAC چیست؟

بزرگ‌ترین مزیت RBAC، سادگی مدل دسترسی است.

به جای اینکه برای هر کاربر Permissionهای جداگانه تعریف کنیم، Permissionها را در Role قرار می‌دهیم.

مثلاً:

Admin → [Create, Read, Update, Delete]

و سپس:

Sarem → Admin

در نتیجه اگر Permission جدیدی به Admin اضافه شود، کاربران دارای این Role نیز آن Permission را دریافت می‌کنند.

این ساختار در پروژه‌هایی که قوانین دسترسی نسبتاً ثابت هستند، بسیار کاربردی است.


مشکل RBAC در سیستم‌های بزرگ

فرض کنید یک شرکت ۵۰۰۰ کاربر دارد.

ساختار سازمانی:

  • شرکت

  • شعبه

  • دپارتمان

  • تیم

حالا فرض کنید یک Manager فقط باید سفارش‌های شعبه خودش را مشاهده کند.

در RBAC ساده ممکن است وسوسه شویم Roleهای زیادی ایجاد کنیم:

  • TehranManager

  • TabrizManager

  • ShirazManager

  • IsfahanManager

اگر تعداد شعبه‌ها، واحدها و شرایط مختلف افزایش پیدا کند، تعداد Roleها نیز می‌تواند زیاد شود.

به این مشکل معمولاً Role Explosion گفته می‌شود.

در اینجا مشخص می‌شود که نقش به‌تنهایی همیشه برای تصمیم‌گیری درباره دسترسی کافی نیست.


ABAC چیست؟

ABAC مخفف Attribute-Based Access Control است.

در ABAC، تصمیم دسترسی فقط بر اساس Role گرفته نمی‌شود.

سیستم می‌تواند ویژگی‌های مختلفی را بررسی کند:

  • ویژگی‌های کاربر

  • ویژگی‌های Resource

  • نوع عملیات

  • شرایط محیط

برای مثال:

آیا این کاربر اجازه مشاهده این سفارش را دارد؟

سیستم می‌تواند بررسی کند:

User

  • department = sales

  • branch = Tehran

  • role = manager

Resource

  • type = order

  • branch = Tehran

  • ownerDepartment = sales

Action

  • read

Environment

  • time = working hours

سپس Policy تصمیم می‌گیرد که درخواست مجاز است یا خیر.


ABAC چگونه تصمیم می‌گیرد؟

می‌توانیم یک Policy ساده داشته باشیم:

کاربرانی که Manager هستند، می‌توانند سفارش‌های شعبه خودشان را مشاهده کنند.

این Policy دیگر صرفاً به Role وابسته نیست.

ممکن است منطق آن چیزی شبیه این باشد:

user.role == "Manager"

و

user.branch == resource.branch

و

action == "read"

اگر همه شرایط برقرار باشند:

Allow

در غیر این صورت:

Deny

اینجاست که ABAC انعطاف بسیار بیشتری نسبت به RBAC پیدا می‌کند.


تفاوت RBAC و ABAC در یک مثال واقعی

فرض کنید یک شرکت چند شعبه دارد.

کارمند علی:

Role = Manager

Branch = Tehran

کارمند رضا:

Role = Manager

Branch = Tabriz

هر دو Manager هستند.

در RBAC ساده، هر دو یک Permission مشابه دارند:

order.read

اما سؤال مهم این است:

آیا علی باید سفارش‌های تبریز را هم ببیند؟

احتمالاً نه.

اینجا ABAC می‌تواند شرط دیگری اضافه کند:

user.branch == order.branch

در نتیجه:

علی → سفارش تهران → مجاز

علی → سفارش تبریز → غیرمجاز

رضا → سفارش تبریز → مجاز

این همان تفاوت مهم بین نقش و شرایط دسترسی است.


RBAC و ABAC چه چیزی را کنترل می‌کنند؟

این دو مدل را می‌توان به شکل زیر مقایسه کرد:

RBAC

تمرکز اصلی:

چه نقشی داری؟

مثلاً:

Admin

Manager

Editor

Customer

ABAC

تمرکز اصلی:

چه ویژگی‌هایی داری و در چه شرایطی می‌خواهی چه عملیاتی روی چه منبعی انجام دهی؟

یعنی:

User + Resource + Action + Environment


آیا ABAC جایگزین RBAC است؟

لزوماً نه.

در بسیاری از سیستم‌های بزرگ، بهترین معماری الزاماً انتخاب یکی از این دو نیست.

می‌توان از RBAC برای سطح بالای دسترسی و از ABAC برای محدودیت‌های دقیق‌تر استفاده کرد.

برای مثال:

کاربر:

Role = Manager

این Role اجازه مشاهده سفارش‌ها را دارد.

اما Policy تعیین می‌کند:

user.branch == order.branch

در نتیجه:

RBAC مشخص می‌کند کاربر چه نوع عملیاتی می‌تواند انجام دهد.

و ABAC مشخص می‌کند این عملیات تحت چه شرایطی مجاز است.

این ترکیب می‌تواند مدل دسترسی قدرتمندتری ایجاد کند.


Permission و Role را با هم اشتباه نگیریم

یکی از اشتباهات رایج در طراحی Authorization این است که Role و Permission را یکی در نظر بگیریم.

Role:

ProductManager

Permission:

product.read

product.create

product.update

ممکن است یک Role چند Permission داشته باشد.

و یک Permission نیز ممکن است در چند Role استفاده شود.

در نتیجه ساختار معمول می‌تواند چیزی شبیه این باشد:

User → Roles → Permissions

و در مدل‌های پیچیده‌تر:

User + Attributes + Resource + Action → Policy Decision


Authentication با Authorization فرق دارد

قبل از ادامه، یک تفاوت مهم دیگر را هم باید مشخص کنیم.

Authentication

یعنی:

تو چه کسی هستی؟

مثلاً کاربر با موفقیت Login کرده است.

Authorization

یعنی:

چه کاری اجازه داری انجام دهی؟

ممکن است کاربر احراز هویت شده باشد، اما اجازه حذف یک محصول را نداشته باشد.

بنابراین RBAC و ABAC بیشتر در حوزه Authorization قرار می‌گیرند، نه Authentication.


RBAC در چه پروژه‌هایی مناسب است؟

RBAC معمولاً انتخاب مناسبی است وقتی که:

  • تعداد Roleها محدود است.

  • قوانین دسترسی نسبتاً ثابت هستند.

  • ساختار سازمانی پیچیدگی زیادی ندارد.

  • مدیریت Permissionها ساده است.

  • نیاز به Policyهای بسیار پویا ندارید.

برای مثال یک پنل مدیریت فروشگاه ممکن است Roleهایی مانند:

Admin

ProductManager

OrderManager

Support

داشته باشد.

در چنین شرایطی RBAC می‌تواند کاملاً کافی باشد.


ABAC چه زمانی ارزش بیشتری پیدا می‌کند؟

ABAC زمانی اهمیت بیشتری پیدا می‌کند که قوانین دسترسی وابسته به Context باشند.

برای مثال:

  • شعبه کاربر

  • دپارتمان کاربر

  • مالک Resource

  • نوع Resource

  • وضعیت Resource

  • زمان درخواست

  • نوع عملیات

  • Tenant

  • موقعیت یا شرایط محیطی

در یک SaaS چندمستاجری، ممکن است بخواهیم کاربر فقط به اطلاعات Tenant خودش دسترسی داشته باشد.

در اینجا یک شرط مهم وجود دارد:

user.tenantId == resource.tenantId

این شرط می‌تواند مستقل از Role بررسی شود.


Multi-Tenant Architecture و ABAC

در سیستم‌های SaaS، مفهوم Tenant بسیار مهم است.

فرض کنید یک API داریم:

GET /api/orders

کاربر از شرکت A وارد سیستم شده است.

حتی اگر Role او:

Admin

باشد، نباید بتواند سفارش‌های شرکت B را مشاهده کند.

پس صرفاً این شرط کافی نیست:

user.role == Admin

باید شرط دیگری نیز وجود داشته باشد:

user.tenantId == order.tenantId

این یکی از نمونه‌های واضحی است که نشان می‌دهد Authorization فقط به Role محدود نمی‌شود.


آیا RBAC ساده‌تر و همیشه بهتر است؟

سادگی همیشه به معنی مناسب بودن برای همه پروژه‌ها نیست.

اگر سیستم کوچک باشد، استفاده از Policyهای پیچیده ممکن است فقط باعث افزایش پیچیدگی شود.

از طرف دیگر، اگر سیستم بزرگ باشد و قوانین دسترسی زیادی داشته باشد، یک RBAC ساده ممکن است به تعداد زیادی Role و Exception تبدیل شود.

بنابراین طراحی Authorization باید از نیاز واقعی سیستم شروع شود.

نه از اینکه کدام مدل «مدرن‌تر» است.


اشتباه رایج: فقط بررسی Role در Backend

یکی از مشکلات امنیتی مهم این است که توسعه‌دهنده فقط در Frontend بررسی کند:

isAdmin === true

و بر اساس آن دکمه حذف را نمایش دهد.

اما مخفی کردن دکمه در Frontend، Authorization واقعی نیست.

کاربر می‌تواند مستقیماً API را صدا بزند.

بنابراین:

Frontend برای تجربه کاربری است.

Backend باید مرجع نهایی Authorization باشد.

مثلاً حتی اگر دکمه Delete در Frontend نمایش داده نشود، API باید خودش بررسی کند که آیا کاربر Permission لازم برای حذف Resource را دارد یا خیر.


RBAC و ABAC در Next.js و ASP.NET Core

در معماری‌هایی مانند:

Next.js → ASP.NET Core API

می‌توان Authentication را از Authorization جدا کرد.

Next.js می‌تواند مسئول بخشی از تجربه کاربری و کنترل‌های UI باشد، اما API باید Authorization را در سمت سرور enforce کند.

در ASP.NET Core نیز می‌توان از Role-Based Authorization و Policy-Based Authorization استفاده کرد.

برای مثال، به جای اینکه فقط بررسی کنیم:

Admin

می‌توان Policyهایی تعریف کرد که شرایط دقیق‌تری را بررسی کنند.

این مدل برای سیستم‌هایی که Permissionهای پیچیده‌تری دارند، انعطاف بیشتری ایجاد می‌کند.


چگونه یک سیستم دسترسی قابل توسعه طراحی کنیم؟

یک معماری مناسب معمولاً بهتر است چند مفهوم را از هم جدا نگه دارد:

User

هویت کاربر.

Role

گروهی از مسئولیت‌ها یا دسترسی‌ها.

Permission

عملیاتی که کاربر می‌تواند انجام دهد.

Resource

منبعی که عملیات روی آن انجام می‌شود.

Policy

قواعدی که مشخص می‌کنند عملیات تحت چه شرایطی مجاز است.

Context

اطلاعات محیطی مورد نیاز برای تصمیم‌گیری.

در نتیجه به جای اینکه تمام منطق Authorization داخل Controllerها پراکنده شود، می‌توان آن را ساختاریافته‌تر طراحی کرد.


یک مدل ذهنی ساده

برای به خاطر سپردن تفاوت این دو مدل:

RBAC

Role → Permission

مثلاً:

Manager → order.read

ABAC

Attributes → Policy → Decision

مثلاً:

Manager + Tehran + Order.Tehran + Read → Allow

این دو مدل رقیب مطلق یکدیگر نیستند.

در بسیاری از معماری‌های واقعی می‌توان از هر دو در کنار یکدیگر استفاده کرد.


جمع‌بندی

RBAC و ABAC دو رویکرد متفاوت برای مدیریت Authorization هستند.

در RBAC، دسترسی بیشتر حول Role می‌چرخد.

در ABAC، تصمیم دسترسی می‌تواند بر اساس مجموعه‌ای از Attributes و Context گرفته شود.

اگر سیستم ساده‌ای دارید، RBAC می‌تواند مدل قابل فهم و مناسبی برای مدیریت دسترسی باشد.

اما زمانی که سیستم شما دارای شعبه‌های متعدد، Tenantها، مالکیت Resource، قوانین سازمانی یا شرایط پویا است، مدل‌های Policy و Attribute-Based می‌توانند کنترل دقیق‌تری ایجاد کنند.

مهم‌تر از انتخاب نام مدل، این است که Authorization در یک سیستم بزرگ قابل فهم، قابل تست، قابل audit و متمرکز در Backend باشد.

چون در نهایت امنیت واقعی سیستم از جایی شروع می‌شود که سرور قبل از اجرای یک عملیات بتواند به‌درستی پاسخ دهد:

«این کاربر، در این شرایط، روی این Resource، اجازه انجام این Action را دارد یا نه؟»