قدرت سیستم مجوزهای جنگو را با این راهنمای جامع احراز دسترسی آزاد کنید. نحوه تعریف، پیادهسازی و مدیریت مجوزها را برای برنامههای وب امن و مقیاسپذیر بیاموزید.
تسلط بر سیستم مجوزهای جنگو: راهنمای جامع برای احراز دسترسی
در حوزه توسعه وب، امنیت از اهمیت بالایی برخوردار است. جنگو (Django)، یک فریمورک قدرتمند وب پایتون، سیستمی قوی و انعطافپذیر برای مدیریت احراز دسترسی کاربران و محافظت از منابع برنامه شما ارائه میدهد. این راهنمای جامع به جزئیات سیستم مجوزهای جنگو میپردازد و مثالهای عملی و بهترین شیوهها را برای پیادهسازی احراز دسترسی امن و مقیاسپذیر در پروژههای جنگو شما ارائه میکند.
درک تفاوت احراز هویت و احراز دسترسی
قبل از ورود به جزئیات سیستم مجوزهای جنگو، درک تفاوت بین احراز هویت (Authentication) و احراز دسترسی (Authorization) بسیار مهم است:
- احراز هویت (Authentication): هویت کاربر را تأیید میکند. به این سوال پاسخ میدهد که "شما کیستید؟". این معمولاً از طریق ترکیب نام کاربری/گذرواژه، ورود از طریق شبکههای اجتماعی یا سایر ارائهدهندگان هویت انجام میشود.
- احراز دسترسی (Authorization): تعیین میکند که یک کاربر احراز هویت شده چه کارهایی مجاز است انجام دهد. به این سوال پاسخ میدهد که "شما مجاز به انجام چه کاری هستید؟". اینجا جایی است که سیستم مجوزهای جنگو وارد عمل میشود.
احراز هویت *قبل* از احراز دسترسی اتفاق میافتد. شما باید بدانید که کاربر کیست، قبل از اینکه بتوانید تعیین کنید چه چیزی را مجاز است دسترسی یا ویرایش کند.
سیستم مجوز داخلی جنگو
جنگو یک سیستم مجوز داخلی بر اساس مدلها، کاربران و گروهها ارائه میدهد. استفاده از آن برای نیازهای اولیه احراز دسترسی ساده است، اما میتوان آن را برای مدیریت سناریوهای پیچیدهتر گسترش و سفارشیسازی کرد.
مجوزهای مدل
جنگو به طور خودکار مجوزهای پیشفرض را برای هر مدل ایجاد میکند، که به شما امکان میدهد کنترل کنید چه کسی میتواند نمونههای آن مدل را ایجاد، بخواند، بهروزرسانی و حذف کند. این مجوزها عبارتند از:
- add_[modelname]: امکان ایجاد نمونههای جدیدی از مدل را فراهم میکند.
- change_[modelname]: امکان بهروزرسانی نمونههای موجود از مدل را فراهم میکند.
- delete_[modelname]: امکان حذف نمونههای مدل را فراهم میکند.
- view_[modelname]: امکان مشاهده نمونههای مدل را فراهم میکند (جنگو 3.1+).
به عنوان مثال، اگر مدلی به نام `Article` دارید، جنگو مجوزهای زیر را ایجاد خواهد کرد:
- `add_article`
- `change_article`
- `delete_article`
- `view_article`
کاربران و گروهها
سیستم احراز هویت داخلی جنگو دو موجودیت اساسی برای مدیریت مجوزها ارائه میدهد:
- کاربران (Users): حسابهای کاربری فردی در برنامه شما.
- گروهها (Groups): مجموعهای از کاربران با مجوزهای مشترک. این روشی قابل نگهداریتر برای اعمال مجوزها به چندین کاربر به طور همزمان است.
میتوانید مجوزها را مستقیماً به کاربران اختصاص دهید یا، به طور معمولتر، مجوزها را به گروهها اختصاص داده و سپس کاربران را به آن گروهها اضافه کنید.
مثال: مدیریت مجوزهای مقاله
فرض کنید یک برنامه وبلاگ با مدل `Article` دارید. میخواهید فقط به کاربران خاصی اجازه ایجاد مقالات جدید، ویرایش مقالات موجود و حذف مقالات را بدهید. در اینجا نحوه پیادهسازی این کار با استفاده از سیستم مجوز داخلی جنگو آورده شده است:
- ایجاد گروهها: گروههایی مانند "Editor" (ویرایشگر) و "Author" (نویسنده) را در پنل ادمین جنگو ایجاد کنید.
- اختصاص مجوزها: مجوزهای `add_article`، `change_article` و `delete_article` را به گروه "Editor" اختصاص دهید. فقط مجوز `add_article` را به گروه "Author" اختصاص دهید.
- افزودن کاربران به گروهها: کاربران مناسب را به گروههای "Editor" و "Author" اضافه کنید.
اکنون، کاربران در گروه "Editor" دسترسی کامل برای مدیریت مقالات خواهند داشت، در حالی که کاربران در گروه "Author" فقط قادر به ایجاد مقالات جدید خواهند بود.
پیادهسازی مجوزها در Viewها
هنگامی که مجوزهای خود را تعریف کرده و به کاربران یا گروهها اختصاص دادید، باید آن مجوزها را در Viewهای خود اعمال کنید. جنگو چندین راه برای انجام این کار ارائه میدهد:
دکوراتور `permission_required`
دکوراتور `@permission_required` راهی ساده برای محدود کردن دسترسی به یک View به کاربرانی با مجوزهای خاص است.
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
@permission_required('myapp.add_article')
def create_article(request):
# Only users with the 'myapp.add_article' permission can access this view
return render(request, 'myapp/create_article.html')
اگر کاربری بدون مجوز لازم سعی در دسترسی به View داشته باشد، بسته به تنظیمات شما، به صفحه ورود هدایت میشود یا خطای 403 Forbidden دریافت میکند.
`LoginRequiredMixin` و `PermissionRequiredMixin` (برای Viewهای کلاس-محور)
برای Viewهای کلاس-محور، میتوانید از `LoginRequiredMixin` و `PermissionRequiredMixin` برای اعمال احراز هویت و احراز دسترسی استفاده کنید:
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.views.generic import CreateView
from .models import Article
class ArticleCreateView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
model = Article
fields = ['title', 'content']
permission_required = 'myapp.add_article'
template_name = 'myapp/article_form.html'
این مثال نشان میدهد که چگونه دسترسی به `ArticleCreateView` را فقط به کاربران احراز هویت شده با مجوز `add_article` محدود کنید.
بررسی دستی مجوزها
همچنین میتوانید مجوزها را به صورت دستی در Viewهای خود با استفاده از متد `has_perm()` روی شیء کاربر بررسی کنید:
from django.shortcuts import render, redirect
def update_article(request, article_id):
article = Article.objects.get(pk=article_id)
if request.user.has_perm('myapp.change_article', article):
# User has permission to update the article
# Implement update logic here
return render(request, 'myapp/update_article.html', {'article': article})
else:
# User does not have permission
return render(request, 'myapp/permission_denied.html')
در این مثال، بررسی میکنیم که آیا کاربر مجوز `change_article` را برای یک نمونه `article` خاص دارد یا خیر. این به شما امکان میدهد مجوزهای سطح شیء (object-level permissions) را پیادهسازی کنید، که در آن مجوزها بر اساس شیء خاصی که به آن دسترسی پیدا میشود، اعطا میگردند.
مجوزهای سفارشی
مجوزهای داخلی جنگو اغلب برای نیازهای اولیه احراز دسترسی کافی هستند. با این حال، در برنامههای پیچیدهتر، ممکن است نیاز به تعریف مجوزهای سفارشی داشته باشید تا منطق تجاری خاص یا الزامات کنترل دسترسی را منعکس کنید.
تعریف مجوزهای سفارشی در مدلها
میتوانید مجوزهای سفارشی را در کلاس `Meta` مدل خود با استفاده از گزینه `permissions` تعریف کنید:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
author = models.ForeignKey('auth.User', on_delete=models.CASCADE)
published_date = models.DateTimeField(blank=True, null=True)
class Meta:
permissions = [
('can_publish_article', 'Can publish article'),
('can_comment_article', 'Can comment on article'),
]
این مثال دو مجوز سفارشی را تعریف میکند: `can_publish_article` و `can_comment_article`. این مجوزها به طور خودکار هنگام اجرای `python manage.py migrate` ایجاد خواهند شد.
استفاده از مجوزهای سفارشی
پس از تعریف مجوزهای سفارشی خود، میتوانید از آنها به همان روش مجوزهای داخلی، با استفاده از دکوراتور `@permission_required`، `PermissionRequiredMixin` یا متد `has_perm()` استفاده کنید.
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
@permission_required('myapp.can_publish_article')
def publish_article(request, article_id):
# Only users with the 'myapp.can_publish_article' permission can access this view
article = Article.objects.get(pk=article_id)
article.published_date = timezone.now()
article.save()
return render(request, 'myapp/article_published.html', {'article': article})
مجوزهای سطح شیء
مجوزهای سطح شیء به شما امکان میدهند دسترسی به نمونههای خاصی از یک مدل را کنترل کنید، به جای اعطای مجوزهای کلی برای همه نمونهها. این برای برنامههایی که کاربران باید فقط بتوانند به منابعی که خودشان مالک آن هستند یا به صراحت به آنها دسترسی داده شده است، دسترسی یا آنها را ویرایش کنند، ضروری است.
پیادهسازی مجوزهای سطح شیء
چندین روش برای پیادهسازی مجوزهای سطح شیء در جنگو وجود دارد:
- بررسی دستی مجوزها: همانطور که قبلاً نشان داده شد، میتوانید از متد `has_perm()` برای بررسی مجوزها برای یک نمونه شیء خاص استفاده کنید.
- استفاده از کتابخانههای شخص ثالث: کتابخانههایی مانند `django-guardian` روشهای ساختارمندتر و قابل استفاده مجددی برای مدیریت مجوزهای سطح شیء ارائه میدهند.
مثال: استفاده از `django-guardian`
`django-guardian` فرآیند اختصاص و بررسی مجوزهای سطح شیء را ساده میکند. در اینجا یک مثال پایه آورده شده است:
- نصب `django-guardian`: `pip install django-guardian`
- پیکربندی `settings.py`: `'guardian'` را به `INSTALLED_APPS` خود اضافه کنید و بکاندهای احراز هویت لازم را پیکربندی کنید.
- اختصاص مجوزها: از تابع `assign_perm()` برای اعطای مجوزها به کاربران یا گروهها برای اشیاء خاص استفاده کنید.
- بررسی مجوزها: از تابع `has_perm()` برای بررسی اینکه آیا کاربر مجوز خاصی را برای یک شیء خاص دارد یا خیر، استفاده کنید.
from guardian.shortcuts import assign_perm, get_perms
# Assign the 'change_article' permission to a user for a specific article
assign_perm('change_article', user, article)
# Check if the user has the 'change_article' permission for the article
if user.has_perm('change_article', article):
# User has permission
pass
`django-guardian` همچنین یک `PermissionListMixin` برای Viewهای کلاس-محور ارائه میدهد که نمایش لیستی از اشیایی که کاربر مجوز دسترسی به آنها را دارد، آسانتر میکند.
مجوزهای جنگو REST Framework
اگر در حال ساخت APIهای REST با جنگو REST Framework هستید، باید از کلاسهای مجوز آن برای کنترل دسترسی به نقاط پایانی API خود استفاده کنید. DRF چندین کلاس مجوز داخلی از جمله موارد زیر را ارائه میدهد:
- `AllowAny`: دسترسی نامحدود به نقطه پایانی API را مجاز میداند.
- `IsAuthenticated`: برای دسترسی به نقطه پایانی API، کاربر باید احراز هویت شده باشد.
- `IsAdminUser`: برای دسترسی به نقطه پایانی API، کاربر باید مدیر باشد.
- `IsAuthenticatedOrReadOnly`: دسترسی فقط خواندنی را برای کاربران احراز هویت نشده مجاز میداند اما برای دسترسی نوشتاری به احراز هویت نیاز دارد.
- `DjangoModelPermissions`: از مجوزهای استاندارد مدل جنگو برای کنترل دسترسی استفاده میکند.
- `DjangoObjectPermissions`: از `django-guardian` برای اعمال مجوزهای سطح شیء استفاده میکند.
استفاده از کلاسهای مجوز DRF
میتوانید کلاسهای مجوز را برای یک View با استفاده از ویژگی `permission_classes` تنظیم کنید:
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
class ArticleList(generics.ListCreateAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticated]
این مثال دسترسی به نقطه پایانی API `ArticleList` را فقط به کاربران احراز هویت شده محدود میکند.
مجوزهای سفارشی DRF
همچنین میتوانید کلاسهای مجوز سفارشی DRF را برای پیادهسازی منطق احراز دسترسی پیچیدهتر ایجاد کنید. یک کلاس مجوز سفارشی باید از `rest_framework.permissions.BasePermission` ارثبری کرده و متدهای `has_permission()` و/یا `has_object_permission()` را بازنویسی کند.
from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow authors of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Instance must have an attribute named `author`.
return obj.author == request.user
این مثال یک کلاس مجوز سفارشی را تعریف میکند که فقط به نویسنده یک مقاله اجازه ویرایش آن را میدهد، در حالی که دسترسی خواندن را برای همه مجاز میسازد.
بهترین شیوههای امنیتی
پیادهسازی یک سیستم مجوز قوی برای ایمنسازی برنامه جنگو شما حیاتی است. در اینجا برخی از بهترین شیوههای امنیتی که باید در نظر داشته باشید، آورده شده است:
- اصل کمترین امتیاز (Principle of Least Privilege): فقط حداقل مجوزهایی را که کاربران برای انجام وظایف خود نیاز دارند، به آنها بدهید. از اختصاص مجوزهای غیرضروری خودداری کنید.
- استفاده از گروهها: مجوزها را از طریق گروهها مدیریت کنید، نه اینکه مجوزها را مستقیماً به کاربران فردی اختصاص دهید. این کار مدیریت را سادهتر کرده و خطر خطا را کاهش میدهد.
- بازرسیهای منظم: به صورت دورهای تنظیمات مجوز خود را بازبینی کنید تا اطمینان حاصل شود که هنوز مناسب هستند و هیچ دسترسی غیرمجازی اعطا نشده است.
- پاکسازی ورودی (Sanitize Input): همیشه ورودی کاربر را پاکسازی کنید تا از حملات تزریق که میتوانند سیستم مجوز شما را دور بزنند، جلوگیری کنید.
- تست کامل: سیستم مجوز خود را به طور کامل تست کنید تا اطمینان حاصل شود که مطابق انتظار عمل میکند و هیچ آسیبپذیری وجود ندارد. تستهای خودکار برای تأیید بررسیهای مجوز بنویسید.
- بهروز بمانید: فریمورک جنگو و کتابخانههای مرتبط خود را بهروز نگه دارید تا از جدیدترین وصلههای امنیتی و رفع اشکالات بهرهمند شوید.
- خطمشی امنیت محتوا (CSP) را در نظر بگیرید: CSP میتواند به جلوگیری از حملات اسکریپتنویسی بین سایتی (XSS) کمک کند، که میتواند برای دور زدن مکانیزمهای احراز دسترسی استفاده شود.
ملاحظات بینالمللیسازی
هنگام طراحی سیستم مجوز خود برای مخاطبان جهانی، جنبههای بینالمللیسازی زیر را در نظر بگیرید:
- نام نقشها: اگر برنامه شما از نقشها (مانند ویرایشگر، نویسنده، مدیر) استفاده میکند، اطمینان حاصل کنید که این نامهای نقش به راحتی قابل ترجمه و از نظر فرهنگی مناسب برای همه زبانهای پشتیبانیشده هستند. استفاده از نسخههای خاص هر زبان برای نام نقشها را در نظر بگیرید.
- رابط کاربری: رابط کاربری خود را طوری طراحی کنید که با زبانها و قراردادهای فرهنگی مختلف سازگار باشد. این شامل فرمتهای تاریخ/زمان، فرمتهای اعداد و جهت متن است.
- مناطق زمانی: هنگام اعطا یا لغو مجوزها بر اساس رویدادهای حساس به زمان، مناطق زمانی مختلف را در نظر بگیرید. مهرهای زمانی را در UTC ذخیره کرده و برای نمایش به منطقه زمانی محلی کاربر تبدیل کنید.
- مقررات حفظ حریم خصوصی دادهها: از مقررات حفظ حریم خصوصی دادهها در کشورهای مختلف (مانند GDPR در اروپا، CCPA در کالیفرنیا) آگاه باشید. مکانیزمهای رضایت مناسب و اقدامات حفاظت از دادهها را پیادهسازی کنید.
- قابلیت دسترسی: اطمینان حاصل کنید که سیستم مجوز شما برای کاربران دارای معلولیت قابل دسترسی است و از استانداردهای قابلیت دسترسی مانند WCAG پیروی میکند.
نتیجهگیری
سیستم مجوز جنگو یک فریمورک قدرتمند و انعطافپذیر برای مدیریت احراز دسترسی در برنامههای وب شما فراهم میکند. با درک ویژگیهای داخلی، مجوزهای سفارشی، مجوزهای سطح شیء و بهترین شیوههای امنیتی، میتوانید برنامههای امن و مقیاسپذیری بسازید که از منابع ارزشمند شما محافظت کنند. به یاد داشته باشید که سیستم مجوز خود را با نیازهای خاص برنامه خود تطبیق دهید و به طور منظم تنظیمات خود را بازبینی و بهروزرسانی کنید تا از اثربخشی آنها اطمینان حاصل کنید.
این راهنما یک مرور جامع از سیستم مجوز جنگو ارائه میدهد. با ساخت برنامههای پیچیدهتر، ممکن است با سناریوهای پیشرفتهتری روبرو شوید. برای راهنمایی بیشتر، از کاوش در مستندات و منابع جامعه جنگو دریغ نکنید.