django 는 user에서 기본적인 권한들을 제공해주고 있다.
is_superuser : createsuper 로 생성한 user 에 대해 True, True일 경우 별도 permission 없이 모든 권한 허용
is_staff : True 일 경우 admin 페이지 접속가능, 나머지는 일반 유저와 동일
is_active : False 일 경우 모든 권한 불허, 로그인도 불가능
어떠한 사용자가 API에 접근해 특정 작업을 수행하려 할 때, request에 담겨오는
user의 정보에 따라 작업의 권한을 줄지 말지 결정하는 것이다
DRF 에서 기본제공하는 Permission 은 다음과 같다.
AllowAny(default) : 인증여부에 상관없이 무조건 허용 (default)
IsAuthenticated : 인증된 사용자에 대한 작업 권한을 허용하고 인증되지 않은 사용에 대한 액세스를 거부
IsAdminUser : Staff 인증 요청에 한해서 허용
IsAuthenticatedOrReadOnly : 인증된 사용자에게는 전체 액세스를 허용하지만 인증되지 않은 사용자에게는 읽기만 허용
DjangoModelPermissions : 인증된 요청에 한해서만 액세스 허용, 추가로 유저별 인증 권한체크를 수행
DjangoModelPermissionsOrAnonReadOnly : DjangoModelPermissions 와 유사하나 비인증 요청에 대해서는 읽기 권한만 허용
DjangoObjectPermissions : 비인증된 요청 거부, 인증된 레코드 접근에 대한 권한체크를 추가로 수행
Custom Permission: 개발자가 custom 하게 permission을 만들어서 사용할 수도 있음
class PostViewSet(ModelViewSet):
serializer_class = PostSerializer
queryset = Post.objects.all()
filter_backends = [DjangoFilterBackend]
filter_class = PostFilter
permission_classes = [IsAuthenticatedOrReadOnly]
ViewSet 내부의 permission_classes 에 추가
위에서 언급한대로 개발자는 자기 입맛대로 액세스 허용권한을 커스텀할 수 있도록 장고가 여러 기능들을 제공해준다.
우선 우선 프로젝트 내부에 permissions.py라는 파일을 생성해준다.
permissions.py
from rest_framework import permissions
class IsAuthorOrReadOnly(permissions.BasePermission):
# 인증된 유저에 대해 목록 조회 / 포스팅 등록 허용
def has_permission(self, request, view):
return request.user.is_authenticated
# 작성자에 한해 Post에 대한 수정 / 삭제 허용
def has_object_permission(self, request, view, obj):
# 읽기 권한 요청이 들어오면 허용
if request.method in permissions.SAFE_METHODS:
return True
# PUT, DELETE 요청에 한해, 작성자에게만 허용, 요청자(request.user)가 객체(Post)의 user와 동일한지 확인
return obj.user == request.user
IsAuthorOrReadOnly라는 이름의 permission을 하나 만들어준다.
해당 권한은 우선 SAFE_METHOD(GET, HEAD, OPTIONS)로 요청이 들어온 경우에는 method를 허용을 해주고, 그 외(PUT, PATCH, DELETE)에는 게시글의 user와 로그인된 user가 동일한 경우에만 권한을 허용해준다.
class PostViewSet(ModelViewSet):
serializer_class = PostSerializer
queryset = Post.objects.all()
filter_backends = [DjangoFilterBackend]
filter_class = PostFilter
permission_classes = [IsAuthorOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
완성~~!!