مدیریت دسترسی مبتنی بر نقش در NestJS

مدیریت دسترسی مبتنی بر نقش در NestJS | معراج پارسا
مدیریت دسترسی مبتنی بر نقش در NestJS | معراج پارسا

سلام دوستان

امروز می‌خوایم درباره یکی از موضوعات مهم و کاربردی تو دنیای برنامه‌نویسی وب صحبت کنیم : مدیریت دسترسی مبتنی بر نقش (RBAC) توی NestJS .

اگه تا حالا با RBAC آشنا نبودید، نگران نباشید ، تو این مقاله می‌خوایم به صورت کامل و جامع درباره RBAC صحبت کنیم و نحوه پیاده‌سازی اون توی NestJS رو بررسی کنیم . پس با من همراه باشید

مدیریت دسترسی مبتنی بر نقش (RBAC) چیه؟

مدیریت دسترسی مبتنی بر نقش (RBAC) یه روش برای کنترل دسترسی به منابع تو یه سیستمه . تو این مدل ، دسترسی به منابع مختلف بر اساس نقش‌های تعیین‌شده برای کاربران کنترل می‌شه . به عبارت دیگه ، هر کاربر یا گروهی از کاربران یه نقش خاص دارن و دسترسی به منابع مختلف بر اساس این نقش‌ها محدود یا مجاز می‌شه .

یه مثال ساده از RBAC

تصور کنید شما یه وب‌سایت با سه نقش مختلف دارید: مدیر ، کاربر معمولی و مهمان . مدیر دسترسی کامل به همه منابع سایت داره ، کاربر معمولی به برخی از منابع دسترسی داره و مهمان فقط به منابع عمومی دسترسی داره . با استفاده از RBAC ، می‌تونید به‌طور دقیق تعیین کنید که هر نقش به چه منابعی دسترسی داره و چه عملیاتی رو می‌تونه انجام بده .

چرا باید از RBAC استفاده کنیم؟

استفاده از RBAC کلی مزیت داره :

  1. مدیریت ساده‌تر دسترسی‌ها : با استفاده از نقش‌ها به‌جای مدیریت دسترسی‌ها برای هر کاربر به‌صورت جداگانه، می‌تونید دسترسی‌ها رو ساده‌تر مدیریت کنید
  2. مقیاس‌پذیری بهتر : با اضافه کردن نقش‌های جدید یا تغییر نقش‌های موجود، می‌تونید به‌راحتی مقیاس‌پذیری سیستم خودتون رو بهبود بدید
  3. امنیت بالاتر : RBAC به شما این امکان رو می‌ده که دسترسی‌های دقیق‌تری رو تنظیم کنید و از دسترسی‌های غیرمجاز جلوگیری کنید

پیاده‌سازی RBAC توی NestJS

حالا که با مفهوم RBAC آشنا شدیم ، بیایید ببینیم چطور می‌تونیم این مدل رو توی NestJS پیاده‌سازی کنیم ، برای این کار، از امکانات NestJS و تکنیک‌های مختلف استفاده خواهیم کرد.

مراحل پیاده‌سازی RBAC
  1. تعریف نقش‌ها و مجوزها
  2. ایجاد گاردهای مبتنی بر نقش
  3. پیکربندی مسیرها و کنترلرها


  • تعریف نقش‌ها و مجوزها

اولین قدم برای پیاده‌سازی RBAC ، تعریف نقش‌ها و مجوزهاست . برای این کار، می‌تونید از Enum‌ ها و پایگاه داده استفاده کنید . برای ایجاد Enum ابتدا یه فایل به نام roles.enum.ts ایجاد کنید و نقش‌ها رو تعریف کنید :

export enum Role { 
  ADMIN = 'admin', 
  USER = 'user',
  GUEST = 'guest', 
}

خب ، حالا نوبت ایجاد مدل پایگاه داده برای نقش‌ها و کاربر هاست . اگه از پایگاه داده استفاده می‌کنید ، باید مدل‌های مربوط به کاربران و نقش‌ها رو تعریف کنید . فرض کنید از TypeORM استفاده می‌کنید :

// user.entity.ts
import { Entity, Column, PrimaryGeneratedColumn, ManyToMany } from 'typeorm';
import { Role as RoleEntity } from './role.entity';

@Entity()
export class User {
   @PrimaryGeneratedColumn()
   id: number;

   @Column()
   username: string;

   @Column()
   password: string;

   @ManyToMany(() => RoleEntity)
   roles: RoleEntity[]; 
}


// role.entity.ts
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

@Entity() export class Role {
   @PrimaryGeneratedColumn()   id: number;
   @Column()   name: string; 
}

توضییحات : ما دو مدل به نامهای user.entity.ts و role.entity.ts ایجاد کردیم . نکته مهمش ارتباط فیلد roles در مدل user به مدل Role هست . همین فیلد نقش هر کاربر رو در خودش نگه داری میکنه


  • ایجاد گاردهای مبتنی بر نقش

گارد‌ها تو NestJS به شما این امکان رو می‌دن که دسترسی به مسیرها رو بر اساس شرایط خاص کنترل کنید . برای پیاده‌سازی RBAC ، باید گاردهایی برای بررسی نقش‌ها ایجاد کنید . برای این کار ، فایل roles.guard.ts رو به این شکل ایجاد کنید :

import { 
     Injectable,
     CanActivate,
     ExecutionContext,
     ForbiddenException } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Role } from './roles.enum';

@Injectable()
 export class RolesGuard implements CanActivate {
   constructor(private reflector: Reflector) {}
   canActivate(context: ExecutionContext): boolean { 
     const requiredRoles = this.reflector.getAllAndOverride<Role[]>('roles',[context.getHandler(),context.getClass(),]);
     if (!requiredRoles) {       return true;     }
     const request = context.switchToHttp().getRequest();
     const user = request.user;
     const hasRole = () => user.roles.some((role) => requiredRoles.includes(role));
     if (user && hasRole()) {       return true;     }
     throw new ForbiddenException('Forbidden');
   } 
}

نکته :

ایجاد دکوراتور نقش : برای راحت‌تر کردن استفاده از گاردهای نقش ، می‌تونید یه دکوراتور ایجاد کنید . فایل roles.decorator.ts به این شکل خواهد بود :

import { SetMetadata } from '@nestjs/common';
import { Role } from './roles.enum';

export const Roles = (...roles: Role[]) => SetMetadata('roles', roles);


  • پیکربندی مسیرها و کنترلرها

حالا که گارد و دکوراتورهای نقش رو ایجاد کردیم ، باید از اون‌ها تو مسیرها و کنترلرهای خودمون استفاده کنیم . به عنوان مثال ، فرض کنید کنترلری به نام CatsController دارید و می‌خواید دسترسی به برخی از مسیرها رو بر اساس نقش‌ها کنترل کنید . فایل cats.controller.ts به این شکل خواهد بود :

import { Controller, Get, Post, UseGuards, Request } from '@nestjs/common';
import { Roles } from './roles.decorator';
import { RolesGuard } from './roles.guard';
import { Role } from './roles.enum';

@Controller('cats')
export class CatsController {
   @Get()
   @Roles(Role.ADMIN)
   @UseGuards(RolesGuard)
   findAll(@Request() req) {
     return 'This action returns all cats';
   }

   @Post()
   @Roles(Role.ADMIN, Role.USER)
   @UseGuards(RolesGuard)
   create(@Request() req) {
     return 'This action adds a new cat';
   }
 }

تو این مثال، فقط کاربرانی با نقش ADMIN به مسیر GET /cats و کاربران با نقش‌های ADMIN یا USER به مسیر POST /cats دسترسی خواهند داشت . به همین سادگی به همین خوشمزگی :)



نکات مهم در پیاده‌سازی RBAC

  1. مدیریت نقش‌ها و مجوزها : نقش‌ها و مجوزها باید به‌طور مداوم مدیریت و به‌روز بشن . اطمینان حاصل کنید که نقش‌ها به درستی به کاربران اختصاص داده شده و دسترسی‌ها به‌طور دقیق تنظیم شده‌ان
  2. آزمون و خطا : پیاده‌سازی RBAC می‌تونه پیچیده باشه. اطمینان حاصل کنید که تمام مسیرها و کنترلرها به درستی تست شدن و دسترسی‌ها به‌درستی اعمال می‌شن
  3. امنیت : اطمینان حاصل کنید که کلیدهای امنیتی و تنظیمات امنیتی به درستی پیکربندی شدن و از آسیب‌پذیری‌های احتمالی جلوگیری می‌شه



جمع بندی

امیدوارم با مطالعه این مقاله ، تونسته باشید با مفهوم RBAC و نحوه پیاده‌سازی اون توی NestJS آشنا بشید. استفاده از RBAC می‌تونه به شما کمک کنه تا امنیت برنامه‌های خودتون رو بهبود بدید و دسترسی‌ها رو به‌طور دقیق مدیریت کنید . اگه سوال یا نظری داشتید ، خوشحال می‌شم که با من در میان بذارید.


مخلصیم :)