This page looks best with JavaScript enabled

Permission Management in Django REST Framework

 ·  ☕ 3 min read

1. Permission Management in DRF

Permission management in Django REST Framework consists of two parts.

  • One is Authentication. It specifies how the user is authenticated, obtaining request.user.
  • The other is Permissions. It performs permission control over Django resources and user categories.

1.1 Authentication Methods

The relevant source is in the rest_framework/authentication.py file. There are three authentication methods in total:

  • BasicAuthentication: HTTP basic authentication.

The frontend sets the username and password, Base64-encoded, in the Authorization HTTP header, and the backend uses it to authenticate the user.

  • TokenAuthentication: Token-based authentication.

The Token in the Authorization HTTP header is used to authenticate the user.

  • SessionAuthentication: Uses Django’s session backend for authentication.

Uses the Django Session Backend to authenticate the user.

Custom Authentication Methods

DRF also allows custom authentication methods. You only need to inherit from the BaseAuthentication class and implement the .authenticate(self, request) method.

1.2 Permission Control Methods

The relevant source is in the rest_framework/permissions.py file. Seven permission control classes are built in in total:

  • AllowAny # No restrictions.
  • IsAuthenticated # Logged-in users.
  • IsAdminUser # Admin users.
  • IsAuthenticatedOrReadOnly # Read-only for non-logged-in users.
  • DjangoModelPermissions # Model-level control.
  • DjangoModelPermissionsOrAnonReadOnly # Anonymous read-only for the Model.
  • DjangoObjectPermissions # Object-level control.

Custom Permission Control

Inherit from BasePermission to customize permission control, implementing one or both of these methods

  • has_permission(self, request, view), a permission check is performed when this endpoint is accessed
  • has_object_permission(self, request, view, obj), a permission check is performed only when the object is accessed

1.3 Handling After Permission Checks

DRF uses the authentication classes to check the requests a user makes.

  • If authentication succeeds, request.user is set to the authenticated User object.
  • If authentication fails, request.user is set to AnonymousUser.

On authentication failure, HTTP 401 Unauthorized is returned.

On permission check failure, HTTP 403 Forbidden is returned.

2. Applying Permission Control

2.1 Authentication URL Setup

1
2
3
urlpatterns = [
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')
]

2.2 Global Permission Control

Global default permissions can be set in settings.py

settings.py

1
2
3
4
5
6
7
8
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.AllowAny',
    )
}

2.3 Permissions for ViewSets

  1. Set the permission_classes class attribute to assign permissions to a viewset.

DRF checks every permission in the tuple; all of them must pass.

1
2
3
4
5
class UserViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    authentication_classes = (SessionAuthentication, )
    permission_classes = (permissions.IsAuthenticated,)
  1. Use the authentication_classes and permission_classes decorators.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from rest_framework.authentication import SessionAuthentication,
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response

@authentication_classes((SessionAuthentication, BasicAuthentication))
@permission_classes((IsAuthenticated,))
def example_view(request, format=None):
    content = {
        'user': unicode(request.user),
        'auth': unicode(request.auth)
    }
    return Response(content)

2.4 Custom Permissions

To customize Permissions, simply inherit from BasePermission and then implement one or both of these methods

  • has_permission(self, request, view), a permission check is performed when this endpoint is accessed
  • has_object_permission(self, request, view, obj), a permission check is performed only when the object is accessed

premissions.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):

    def has_permission(self, request, view):
        if request.method in permissions.SAFE_METHODS:
            return True

    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True

Note that if you implement get_object yourself, you need to use self.check_object_permissions(self.request, obj) to perform the permission check.

1
2
3
4
def get_object(self):
    obj = get_object_or_404(self.get_queryset())
    self.check_object_permissions(self.request, obj)
    return obj

3. References


微信公众号
WRITTEN BY
微信公众号