본문 바로가기

Django

django api_view 사용할때 permission custom하기

해당 포스팅 내용의 기본 사항은 FBV(함수형 뷰)를 기반으로 작성된다.

permissions 란?

인증 및 제한과 함께 사용 권한은 request에 액서스를 허용할지, 거부할지를 결정하게 된다.

django에서의 권한을 알아보면 대표적으로 is_superuser, is_staff, is_active 가 있다.

is_superuser는 create super로 생성한 user에 대해 True이며 해당 계정의 is_superuser가 True이면 permission에 걸리지 않고 모든 권한에 대해서 접근 허용이 된다.

is_staff는 True일 경우 우리가 잘 아는 admin페이지로 접속 가능하고 나머지는 일반 유저와 동일한 형태를 가진다.

is_active는 계정 활성이라 생각하면 된다. 만약 False이면 로그인 조차 불가능해진다.

DRF에서의 권한 은 여러가지가 있는데 알아두면 확실히 좋다.

AllowAny인증여부에 상관없이 view호출 허용이 가능하다.

IsAuthenticated인증된 요청에 한해서 view 호출 허용이 가능하다.

IsAdminUser 는 Staff 인증 요청에 한해서 view 호출 허용이 가능하다.

IsAuthenticatedOrReadOnly 는 비인증 요청에게는 읽기 권한만 허용 가능하다. (로그인 안된 유저들은 읽기만 가능)

DjangoModelPermissions 는 인증된 요청에 한해서만 view 호출 허용, 추가로 유저별 인증 권한체크를 수행

DjangoModelPermissionsOrAnonReadOnly 는 위의 내용과 유사하지만 비인증 요청에 대해서는 읽기 권한만 허용 된다.

DjangoObjectPermissions 는 비인증된 요청 거부, 인증된 레코드 접근에 대한 권한체크를 추가로 수행

Permission을 커스텀할때 알아야할점

커스텀 하기 위해선 거기에 맞게 클래스를 작성해줘야하는데 rest_framework에서 제공해주는 BasePermission 를 상속 받고 작성해야한다.

BasePermission을 타고 들어가보면 두가지 함수를 볼 수 있는데 각각 함수에 대해 알아보겠다.

has_permission(request, view) 는 뷰 호출 접근 권한, APIView접근시 체크

has_object_permission(request, view, obj) 는 개별 레코드 접근 권한, APIView의 get_object 함수를 통해 object 획득 시 체크, 브라우저를 통한 API 접근시에 Create/Update Form 노출 여부 확인 시에 사용된다.

여기서 대부분 has_object_permission만 사용할 예정이다.

커스텀 해보기

글만 나열되어있으면 읽기 싫을것 같아 코드를 보며 이해해보겠다.

일단 새로운 파일을 하나 만든다. 경로는 자신이 따로 깔끔하게 정리해서 볼 수 있는곳에 정리하면 된다. (물론 파일 이름도 자신이 알아서 정하면 된다.)

# ../permissions.py
from rest_framework.permissions import BasePermission

class IsOwner(BasePermission):
      """게시물 작성자만 접근 가능하게 하기"""
    def has_object_permission(self, request, view, obj):
          if request.user.is_authenticated:
              if request.user == obj.user:
                  return True
            return False
        else:
              return False

위의 코드는 간단하게 나타내었지만 작성자 마음대로 어떻게든 변형시켜 사용할 수 있다.

view에서의 사용방법

@api_view(['POST', 'GET'])
@permission_classes([IsOwner])  # FBV에서는 데코레이터로 선언해주면 된다.
def index(request):
      pass