인증
과는 별개로인가
(코드에 접근을 요청하는 주체에 대한 권한)를 설정할 수 있다.
인증
: 로그인과 같이 요청하는 주체가 누구인지 확인인가
: 요청하는 주체에 따라 사용가능한지 아닌지 권한 설정- ex)
- 일반 사용자가 로그인 ->
인증
- 일반 사용자는 관리자 페이지 접속 불가 ->
인가
1-1) 기본 권한 설정
DEFAULT_PERMISSION_CLASSES
를 통해 기본 권한을 전역적으로 설정 가능하다.# settings.py REST_FRAMEWORK = { 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }
1-2) Default
따로 설정하지 않으면 기본적으로 모든 접근을 허용한다.
'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.AllowAny', ]
APIView
클래스를 상속받은View
클래스에는permission_classes
통해 권한 설정 가능settings.py
에 설정된 기본 설정은 무시된다.# example_app/views.py from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView class ExampleView(APIView): permission_classes = [IsAuthenticated] def get(self, request, format=None): content = { 'status': 'request was permitted' } return Response(content)
rest_framework.permissions
에서 제공하는 기본 권한 종류
1) AllowAny
요청이 인증되었는지 여부에 관계없이 무제한 액세스를 허용
2) IsAuthenticated
인증된 사용자에 대해서만 권한 허용
3) IsAdminUser
user.is_staff
설정이True
인 사용자에 대해서만 권한 서용
4) IsAuthenticatedOrReadOnly
- 인증된 사용자는 모든 권한 허용
- 인증되지 않은 사용자는 읽기 (
GET
,HEAD
,OPTIONS
) method 에서만 허용
5) 그밖의 Permissions
- DjangoModelPermissions
- DjangoModelPermissionsOrAnonReadOnly
- DjangoObjectPermissions
기본 종류 외에도
BasePermission
을 상속받아 권한 설정을 커스텀할 수 있다.
requeset.method
에 대한 권한 설정 가능하다.view.kwargs.get()
을 통해 view의 request parameter에 접근할 수 있다.- 비트연산자를 통해 여러 Permissions을 구성할 수 있다.
user.type
가"manager"
이면 모든 권한 허용- 아닐 경우
order_id
라는 주문 식별값을 request parameter로 받아서 작성자인지 확인 후 모든 권한 허용- 작성자가 아닐 경우
GET
,POST
메소드만 허용
# order/permissions.py
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import APIException
from rest_framework import status
from order.models import Order as OrderModel
class GenericAPIException(APIException):
def __init__(self, status_code, detail=None, code=None):
self.status_code=status_code
super().__init__(detail=detail, code=code)
class IsManagerOrIsAuthorOrIsAuthenticatedReadOnly(BasePermission):
"""
관리자는 모두 가능, 작성자는 본인의 주문에 대해서만 모두 가능, 로그인 사용자는 조회, 생성만 가능
"""
SAFE_METHODS = ('GET', 'POST')
message = '접근 권한이 없습니다.'
def has_permission(self, request, view):
user = request.user
if not user.is_authenticated:
response ={
"detail": "서비스를 이용하기 위해 로그인 해주세요.",
}
raise GenericAPIException(status_code=status.HTTP_401_UNAUTHORIZED, detail=response)
if user.is_authenticated and user.type == "manager":
return True
order_id = view.kwargs.get('id', None)
if order_id:
try:
order_author = OrderModel.objects.get(id=order_id).user
except OrderModel.DoesNotExist:
response ={
"detail": "주문을 찾을 수 없습니다.",
}
raise GenericAPIException(status_code=status.HTTP_404_NOT_FOUND, detail=response)
else:
order_author = user
if user.is_authenticated and order_author == user:
return True
if user.is_authenticated and request.method in self.SAFE_METHODS:
return True
return False
# order/views.py
from order.permissions import IsManagerOrIsAuthorOrIsAuthenticatedReadOnly
# 주문 CRUD View
class OrderView(APIView):
permission_classes = [IsManagerOrIsAuthorOrIsAuthenticatedReadOnly]
# 주문 조회
def get(self, request, id):
...
비트 연산자를 통해
IsAuthenticatedOrReadOnly
작성
# example_app/views.py
from rest_framework.permissions import BasePermission, IsAuthenticated, SAFE_METHODS
from rest_framework.response import Response
from rest_framework.views import APIView
class ReadOnly(BasePermission):
def has_permission(self, request, view):
return request.method in SAFE_METHODS
class ExampleView(APIView):
permission_classes = [IsAuthenticated|ReadOnly]
def get(self, request, format=None):
content = {
'status': 'request was permitted'
}
return Response(content)