Django REST Framework permission class
DRF의 Permission Class는 API 요청에 대해 사용자가 접근 권한이 있는지를 판단
1. Permission Class란
Permission Class는 요청을 보낸 사용자가 특정 API 엔드포인트에 접근할 권한이 있는지 확인
API 요청을 허용하거나 거부할 수 있는 기본 도구이며 DRF는 기본적으로 몇 가지 권한 클래스를 제공한다.
이를 커스터마이징하여 다양한 권한 로직을 구현할 수 있음
2. DRF의 기본 권한 클래스
AllowAny
누구나 접근 가능
로그인 여부와 상관없이 모든 요청을 허용함
from rest_framework.permissions import AllowAny
class PublicAPIView(APIView):
permission_classes = [AllowAny]
def get(self, request):
return Response({"message": "Anyone can access this API"})
IsAuthenticated
로그인된 사용자만 접근 가능
로그인되지 않은 사용자는 401 Unauthorized 에러
from rest_framework.permissions import IsAuthenticated
class AuthenticatedAPIView(APIView):
permission_classes = [IsAuthenticated]
def get(self, request):
return Response({"message": f"Hello, {request.user.username}"})
IsAdminUser
관리자인 사용자만 접근 가능
관리자가 아닌 사용자는 403 Forbidden 에러
from rest_framework.permissions import IsAdminUser
class AdminAPIView(APIView):
permission_classes = [IsAdminUser]
def get(self, request):
return Response({"message": "Welcome, Admin"})
3. 커스텀 권한 클래스 작성하기
기본 권한 클래스로 해결되지 않는 세부적인 권한 로직은 커스텀 클래스를 통해 구현할 수 있음
작성자만 수정/삭제 가능, 조회는 누구나 가능
from rest_framework.permissions import BasePermission
class IsAuthorOrReadOnly(BasePermission):
"""
작성자만 수정/삭제 가능하고 조회는 모든 사용자 허용
"""
def has_object_permission(self, request, view, obj):
# 읽기 요청(GET, HEAD, OPTIONS)은 모두 허용
if request.method in ['GET', 'HEAD', 'OPTIONS']:
return True
# 작성자만 쓰기 요청(PUT, DELETE)을 허용
return obj.author == request.user
뷰에 적용
from rest_framework.permissions import IsAuthenticated
from .permissions import IsAuthorOrReadOnly
class ProductDetailAPIView(APIView):
permission_classes = [IsAuthenticated, IsAuthorOrReadOnly] # 로그인과 작성자 확인
def get_object(self, pk):
return get_object_or_404(Product, pk=pk)
def get(self, request, pk):
product = self.get_object(pk)
serializer = ProductSerializer(product)
return Response(serializer.data)
def put(self, request, pk):
product = self.get_object(pk)
serializer = ProductSerializer(product, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
def delete(self, request, pk):
product = self.get_object(pk)
product.delete()
return Response({"message": "Product deleted"})
4. 메서드별로 다른 권한 적용하기
메서드별로 서로 다른 권한 로직이 필요하다면 permission_classes를 클래스 단위로 설정하는 대신, get_permissions 메서드를 오버라이드하여 메서드별 권한을 적용할 수 있음
조회는 누구나 가능, 삭제는 로그인 사용자만 가능
from rest_framework.permissions import AllowAny, IsAuthenticated
class ProductAPIView(APIView):
def get_permissions(self):
if self.request.method == 'GET':
return [AllowAny()] # 조회는 누구나 가능
elif self.request.method == 'DELETE':
return [IsAuthenticated()] # 삭제는 로그인 필요
return super().get_permissions()
def get(self, request):
return Response({"message": "Anyone can view this"})
def delete(self, request):
return Response({"message": "Only logged-in users can delete"})
5. DRF 권한 클래스 사용 팁
권한 클래스 순서: 여러 권한 클래스를 설정한 경우, 첫 번째로 실패하는 권한이 반환하는 에러가 클라이언트에 표시됨
request.method 활용: 메서드(GET, POST 등)에 따라 권한을 다르게 설정할 수 있음
request.user와 obj.author 비교: 특정 객체의 작성자와 현재 요청한 사용자를 비교하여 권한을 제어 가능
6. Postman으로 테스트해보기
로그인 여부 확인: 401 Unauthorized 또는 200 OK 응답 확인
작성자 확인: 작성자가 아닌 사용자가 수정/삭제 요청을 보내면 403 Forbidden 응답
메서드별 권한 확인: GET은 모두 허용, DELETE는 로그인한 사용자만 가능