حمزه قائم پناه
حمزه قائم پناه
خواندن ۴ دقیقه·۵ ماه پیش

همه چیز درباره سیستم اعتبارسنجی جنگو

به روش‌های متفاوتی میشه توی جنگو پرمیژن‌ها رو تعریف کرد، دو روش اصلی رو اینجا بررسی می‌کنیم:

  • پرمیژن‌ها می‌تونن در سطح model باشن (add, change, delete , view) که اینها به طور پیش‌فرض توسط خود جنگو تعریف میشن و ما می‌تونیم سطح‌های کاستوم دیگه‌ای تعریف کنیم. و در پنل django admin میشه گروه‌بندی تعریف کرد و این سطح دسترسی‌ها رو به گروه‌ها و یا مستقیم به کاربرها داد.
  • خود Django REST Framework هم کلاس‌های پرمیژن خودش رو داره (مثل IsAuthenticated, IsAdminUser) و همینطور ما می‌تونیم کلاس‌های پرمیژن کاستوم DRF رو تعریف کنیم.

ساخت سوپر یوزر با کامند:

python manage.py createsuperuser --username=joe --email=joe@example.com

احراز هویت کاربر:

با نام‌کاربری و پسورد لاگین میشه و یوزر برمی‌گردونه و اگر وجود نداشت None میده:

user = authenticate(username=&quotjohn&quot, password=&quotsecret&quot) # Asynchronous version: aauthenticate()

سطح دسترسی:

جنگو یک سیستم پرمیژن داخلی داره که باهاش میشه به کاربرها یا گروهی از کاربرها، یک دسترسی خاص داد که از طریق Django admin site انجام میشه. که به این صورته:

  • دسترسی به دیدن ویوها محدود به کاربرهایی که دسترسی view یا change برای اون object ها رو دارن.
  • دسترسی به ویو افزودن فقط به کاربرایی داده میشه که این دسترسی add رو دارن.
  • دسترسی ویرایش، محدود به کاربرایی هست که دسترسی change رو برای اون object ها رو دارن.

دسترسی‌ها می‌تونه محدود به ازای هرنوع object نباشه و به ازای یک object خاص باشه. که به کمک متد های زیر انجام میشه:

has_view_permission(), has_add_permission(), has_change_permission() and has_delete_permission()

مشابه همه جنگو مدل‌ها، از طریق شی کاربر میشه با پرمیژن‌هاش کار کرد:

myuser.groups.set([group_list]) myuser.groups.add(group, group, ...) myuser.groups.remove(group, group, ...) myuser.groups.clear() myuser.user_permissions.set([permission_list]) myuser.user_permissions.add(permission, permission, ...) myuser.user_permissions.remove(permission, permission, ...) myuser.user_permissions.clear()

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

درباره Proxy model ها:

این مدل‌ها دقیقا مشابه مدل معمولی هستن، با این تفاوت که پرمیژن‌هاشون برای خودشونه و ارث نمیبرن:

class Person(models.Model): class Meta: permissions = [(&quotcan_eat_pizzas&quot, &quotCan eat pizzas&quot)] class Student(Person): class Meta: proxy = True permissions = [(&quotcan_deliver_pizzas&quot, &quotCan deliver pizzas&quot)] >>> content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False) >>> student_permissions = Permission.objects.filter(content_type=content_type)

چک لاگین بودن کاربر:

اگر لاگین نباشه، request.user یک شی از AnonymousUser برمی‌گردونه.

if request.user.is_authenticated: # user = await request.auser() for async

محدود کردن بخش‌ها به ورود کاربر:

  • میشه از متد is_authenticated که قبلا گفتیم استفاده کرد.
  • میشه از دکوریتور @login_required استفاده کرد. که اگر لاگین نباشه میفرسته صفحه لاگین.
  • این دکوریتورهم جایی شاید به کارتون بیاد: @staff_member_required
  • استفاده از mixin به نام LoginRequiredMixin در class-based views
  • استفاده از دکوریتور user_passes_test که به عنوان پارامتر اسم یک متد رو میگیره و اگر False برگردونه، کاربر رو می‌فرسته صفحه ریدایرکتی که بهش دادیم
  • استفاده از دکوریتور permission_required که به عنوان پارامتر اسم پرمیژن رو می‌گیره.
    استفاده از mixin به نام PermissionRequiredMixin برای class-based views

نامعتبر کردن session بعد از تغییر رمزعبور:

به طور معمول در جنگو یک hash در session وجود داره که با هر درخواست کاربر این hash چک میشه که یکسان باشه و اینه که این امکان رو میده که کاربر با تغییر پسوردش، همه از همه session هاش log out بشه. اگر صفجه تغییر پسورد خودتون رو دارین با فراخونی متد زیر، بعد از تغییر پسورد، دیگه کاربر خودش رو لاگ‌اوت نمی‌کنه:

update_session_auth_hash(request, form.user)

Django REST Framework Permissions

پرمیژن‌ها در REST framework همیشه به صورت لیستی از پرمیژن‌های کلاس تعریف میشن. قبل از اجرای بدنه اصلی view هر پرمیژن توی لیست چک میشه و اگر پرمیژنی ناموفق بشه اکسپشن exceptions.PermissionDenied or exceptions.NotAuthenticated برمی‌گردونه و کد ویو اجرا نمیشه.

دسترسی سطح object

همینطور دسترسی سطح object هم پشتیبانی میشه که به این صورت میشه چک کردش:

obj = get_object_or_404(self.get_queryset(), pk=self.kwargs[&quotpk&quot]) self.check_object_permissions(self.request, obj)

مشخص کردن سطح دسترسی

میشه با مشخص کردن DEFAULT_PERMISSION_CLASSES در setting مشخص کرد که سطح پیش‌فرض دسترسی چی باشه.

و می‌تونیم سطح دسترسی class-based view ها رو به ازای هر view یا viewset مشخص کنیم:

permission_classes = [IsAuthenticated]

و یا برای function-based view ها:

@permission_classes([IsAuthenticated])

در عمل چطور پیاده کنم؟ (روش پیشنهادی)

۱- توی پنل ادمین جنگو گروه مورد نظرت رو تعریف کنین و کاربری رو که می‌خوای به این گروه اد کن.

۲- کلاس کاستوم پرمیژن رو تعریف کن:

from rest_framework.permissions import BasePermission from django.contrib.auth.models import Group class IsInGroup(BasePermission): group_name = None def has_permission(self, request, view): return request.user and request.user.groups.filter(name=self.group_name).exists() class IsInAdminGroup(IsInGroup): group_name = 'admin' class IsInEditorGroup(IsInGroup): group_name = 'editor' class IsInViewerGroup(IsInGroup): group_name = 'viewer'

۳- توی ویو Group-based پرمیژن رو تعریف کن:

from rest_framework.views import APIView from rest_framework.permissions import IsAuthenticated, AllowAny class MyCustomView(APIView): permission_classes_by_action = { 'default': [IsAuthenticated], 'retrieve': [IsInViewerGroup], .... } def get_permissions(self): try: # Return the permission classes based on the action return [permission() for permission in self.permission_classes_by_action[self.request.method.lower()]] except KeyError: # Return the default permission classes if the action is not explicitly specified return [permission() for permission in self.permission_classes_by_action['default']] def get(self, request, *args, **kwargs): # Your GET logic here pass


منابع:

https://docs.djangoproject.com/en/5.0/topics/auth/default/

https://www.django-rest-framework.org/api-guide/permissions/#django-rest-framework-role-filters


جنگوdjangoauthentication
مهندس نرم‌افزار و عاشق توسعه فردی - مهندس نرم‌افزار - اکس هم بنیان‌گذار و مدیرفنی و پرداکت استارتاپ کشمون
شاید از این پست‌ها خوشتان بیاید