Computer Science/BackEnd

Django for APIs | #6 Permissions

토마토. 2022. 10. 1. 17:16
Permissions
create a new user

localhost:8000/admin 에서 user를 직접 추가해준다. 

 

add log in to the browsable API
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('api-auth/', include('rest_framework.urls')),
    path('api/v1/', include('posts.urls')),
    path('admin/', admin.site.urls),
]

 

AllowAny

디폴트로 설정되어있는 것

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.AllowAny',
    ]
}

 

View-Level Permissions
from rest_framework import generics, permissions


from .models import Post
from .serializers import PostSerializer

# Create your views here.


class PostList(generics.ListCreateAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    queryset = Post.objects.all()
    serializer_class = PostSerializer


class PostDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (permissions.IsAuthenticated,)
    queryset = Post.objects.all()
    serializer_class = PostSerializer

위에서 추가한 permission_classes 덕분에 이제 로그인 없이는 HTTP 403 Forbidden이 return된다. 

모든 보기에 대해 권한을 변경하기보다는, 프로젝트 수준에서 권한을 변경하는 것이 낫다. 

 

Project-Level Permissions

project-level permission setting의 종류

  • AllowAny - full access
  • IsAuthenticated - 등록된 user만 접근 가능
  • IsAdminUser - admin, superuser만 접근 가능
  • IsAuthenticatedOrReadOnly  - unauthorized user도 view는 가능, authenticated user만 write/edit/delete 가능
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ]
}

 

Custom permissions
class BasePermission(object):
    def has_permission(self, request, view):
        return True

    def has_object_permission(self, request, view, obj):
        return True

=> 이런 식으로 Django REST Framework에 BasePermission 클래스가 정의되어있다. 

encode/django-rest-framework: Web APIs for Django. 🎸 (github.com)

 

from rest_framework import permissions


class IsAuthorOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

 

rest_framework의 permissions를 불러온다. 

permissions의 BasePermission 클래스를 상속받아서 포스트 프로젝트에 맞는 IsAuthorOrReadOnly 클래스를 만든다. 

has_object_permission 함수를 재정의한다. 

SAFE_METHODS에 포함된 HTTP 동사가 있으면 읽기 전용 요청이고 권한이 부여된다. 

그게 아닌 경우 객체의 author와 request.user가 일치하는 경우에만 true를 반환한다. 

 

 

from rest_framework import generics, permissions


from .models import Post
from .permissions import IsAuthorOrReadOnly
from .serializers import PostSerializer

# Create your views here.


class PostList(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer


class PostDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = (IsAuthorOrReadOnly, )
    queryset = Post.objects.all()
    serializer_class = PostSerializer

 

 

Conclusion

보안은 API의 매우 중요한 부분!