به روشهای متفاوتی میشه توی جنگو پرمیژنها رو تعریف کرد، دو روش اصلی رو اینجا بررسی میکنیم:
python manage.py createsuperuser --username=joe --email=joe@example.com
با نامکاربری و پسورد لاگین میشه و یوزر برمیگردونه و اگر وجود نداشت None میده:
user = authenticate(username="john", password="secret") # Asynchronous version: aauthenticate()
جنگو یک سیستم پرمیژن داخلی داره که باهاش میشه به کاربرها یا گروهی از کاربرها، یک دسترسی خاص داد که از طریق Django admin site انجام میشه. که به این صورته:
دسترسیها میتونه محدود به ازای هرنوع 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 رو از دیتابیس بگیریم.
این مدلها دقیقا مشابه مدل معمولی هستن، با این تفاوت که پرمیژنهاشون برای خودشونه و ارث نمیبرن:
class Person(models.Model): class Meta: permissions = [("can_eat_pizzas", "Can eat pizzas")] class Student(Person): class Meta: proxy = True permissions = [("can_deliver_pizzas", "Can deliver pizzas")] >>> 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
به طور معمول در جنگو یک hash در session وجود داره که با هر درخواست کاربر این hash چک میشه که یکسان باشه و اینه که این امکان رو میده که کاربر با تغییر پسوردش، همه از همه session هاش log out بشه. اگر صفجه تغییر پسورد خودتون رو دارین با فراخونی متد زیر، بعد از تغییر پسورد، دیگه کاربر خودش رو لاگاوت نمیکنه:
update_session_auth_hash(request, form.user)
پرمیژنها در REST framework همیشه به صورت لیستی از پرمیژنهای کلاس تعریف میشن. قبل از اجرای بدنه اصلی view هر پرمیژن توی لیست چک میشه و اگر پرمیژنی ناموفق بشه اکسپشن exceptions.PermissionDenied or exceptions.NotAuthenticated برمیگردونه و کد ویو اجرا نمیشه.
همینطور دسترسی سطح object هم پشتیبانی میشه که به این صورت میشه چک کردش:
obj = get_object_or_404(self.get_queryset(), pk=self.kwargs["pk"]) 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