🛡 ساخت APIهای امن با Role-Based Access Control در ASP.NET Core
🔐 در Authentication به شما میگوید کاربر کیست،
اما Authorization به شما میگوید کاربر چه کاری میتواند انجام دهد.
بیشتر توسعهدهندگان NET. در ابتدا با بررسیهای سادهی نقش (Role-Based Checks) شروع میکنند:
«آیا این کاربر Admin است؟» 👀
اما وقتی برنامه رشد میکند، خیلی زود متوجه میشوید که فقط نقشها کافی نیستند.
به مجوزهای جزئیتر (Granular Permissions) نیاز دارید که بتوان آنها را بهصورت انعطافپذیر ترکیب و تخصیص داد.
اینجاست که Role-Based Access Control (RBAC) میدرخشد. ✨
بهجای اینکه در همهجا در کد نقشها را چک کنید، شما مجوزهای خاص (Permissions) را تعریف میکنید
و نقشها را طوری طراحی میکنید که آن مجوزها را حمل کنند.
ممکن است یک کاربر نقش Manager داشته باشد،
اما چیزی که اهمیت دارد این است که آیا او مجوز users:delete را دارد یا نه. 🧾
بیایید ببینیم چطور میتوانیم یک سیستم احراز مجوز انعطافپذیر و مبتنی بر مجوز در ASP.NET Core بسازیم. 🚀
🧩 درک اجزای اصلی RBAC
مدل RBAC از سه جزء کلیدی تشکیل شده است که با هم کار میکنند:
👤 Users → اختصاص داده میشوند به → 🧑💼 Roles → که شامل هستند از → 🔑 Permissions
🔄 جریان کار به این صورت است:
🔹️Users (کاربران):
افراد واقعی که از سیستم شما استفاده میکنند.
🔹️Roles (نقشها):
گروهی از مجوزهای مرتبط (مثل Admin، Manager، Editor).
🔹️Permissions (مجوزها):
عملیات خاصی که کاربران میتوانند انجام دهند
(مثل users:read، orders:create، reports:delete).
✨ زیبایی RBAC در انعطافپذیری آن است.
میتوانید چندین نقش به یک کاربر اختصاص دهید
و نقشها را بدون تغییر در تخصیص کاربران ویرایش کنید.
به همهی Managerها میخواهید امکان export گزارشها بدهید؟
فقط مجوز reports:export را به نقش Manager اضافه کنید ✅
این روش بسیار قابل نگهداریتر است
تا اینکه بخواهید در کد بررسی کنید که آیا کسی Admin یا Super Manager است.
علاوه بر این، RBAC یک نقطهی گسترش اضافی فراهم میکند:
میتوانید برای برخی کاربران مجوزهای سفارشی ایجاد کنید
بدون اینکه نیاز به ساخت نقشهای جدید باشد. 💡
⚙️ ساخت یک Authorization Handler سفارشی در ASP.NET Core
در سیستم احراز مجوز (Authorization) در ASP.NET Core، مفاهیم اصلی بر پایهی Policyها و Requirementها ساخته میشوند.
در این بخش، میخواهیم یک Handler سفارشی بسازیم که مجوزها (Permissions) را از داخل Claims کاربر بررسی کند. 🔍
🧠 کد پیادهسازی Handler سفارشی
public class PermissionAuthorizationRequirement(params string[] allowedPermissions)
: AuthorizationHandler<PermissionAuthorizationRequirement>, IAuthorizationRequirement
{
public string[] AllowedPermissions { get; } = allowedPermissions;
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext context,
PermissionAuthorizationRequirement requirement)
{
foreach (var permission in requirement.AllowedPermissions)
{
bool found = context.User.FindFirst(c =>
c.Type == CustomClaimTypes.Permission &&
c.Value == permission) is not null;
if (found)
{
context.Succeed(requirement);
break;
}
}
return Task.CompletedTask;
}
}