노트

DRF 인증과 권한

DRF Authentication and Permissions

백엔드#django#security · 연결된 개념 7개

쉽게 말하면

DRF 인증과 권한은 공연장 입구 직원이 표만 보고 누구인지 확인하고, 좌석 앞 직원이 그 자리에 앉아도 되는지 따로 판단하는 구조예요. 누구인지 확인하는 단계에서는 아무도 막지 않죠.

비유가 깨지는 곳 실제 거절 코드는 헷갈려요. 인증됐는데 권한이 없으면 403, 인증 정보가 없으면 첫 인증 클래스가 WWW-Authenticate를 줄 수 있을 때만 401이고 SessionAuthentication이면 403이에요.

DRF는 요청 처리를 두 단계로 나눈다. 인증 클래스(authentication class)는 요청을 보낸 사용자가 누구인지 식별해 request.user·request.auth를 채우기만 하고, 권한 클래스(permission class)가 그 사용자에게 이 요청을 허용할지 결정한다. 인증만으로는 요청이 막히지 않는다(인증과 인가).

인증 클래스

방식보내는 값특징
SessionAuthentication세션 쿠키장고 로그인 세션 재사용, CSRF(Cross-Site Request Forgery) 검사 필요
BasicAuthenticationAuthorization: Basic base64(id:pw)매 요청에 비밀번호. HTTPS 필수, 주로 테스트용
TokenAuthenticationAuthorization: Token <키>DB에 토큰 저장. 행을 지우면 즉시 무효
JWT(JSON Web Token, simplejwt)Authorization: Bearer <access>DB 조회 없이 서명 검증. 만료 전 강제 무효화가 어려움
  • TokenAuthentication은 rest_framework.authtoken 앱을 추가하고 마이그레이션해야 한다. 회원 가입 때 post_save 시그널로 토큰을 만들고, 로그아웃 때 토큰 행을 지운다
  • simplejwt는 짧은 access 토큰과 긴 refresh 토큰을 주고, /api/token/refresh/로 access를 다시 받는다. 회전(rotation)·차단 목록(blacklist) 설정은 JWT를 본다
  • 세션 인증을 쓰면 상태를 바꾸는 요청에 CSRF 토큰이 필요하다(Django의 CSRF 방어)

권한 클래스

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ["rest_framework.authentication.TokenAuthentication"],
    "DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
}
 
class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:   # GET, HEAD, OPTIONS
            return True
        return obj.owner == request.user
 
class ReviewDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly]
  • 전역 기본값을 두고 뷰마다 permission_classes로 덮어쓴다
  • has_permission은 요청 단위(로그인 여부, 관리자 여부), has_object_permission은 객체 단위(작성자만 수정)로 검사한다. 객체 권한은 get_object()를 부를 때만 검사되므로, 목록 뷰에서는 get_queryset으로 따로 걸러야 한다
  • 인증은 됐지만 권한이 없으면 403이 나간다. 인증 정보가 없을 때는 첫 번째 인증 클래스가 WWW-Authenticate 헤더를 줄 수 있으면(TokenAuthentication·BasicAuthentication) 401, 그렇지 않으면(SessionAuthentication) 403이다
  • 요청 빈도 제한은 권한과 비슷한 자리에서 요청 제한 (Throttling)이 맡는다
flowchart TD
  R[요청] --> A["인증 클래스들"]
  A --> U["request.user · request.auth 채움"]
  U --> P{"권한 클래스 통과?"}
  P -->|예| V[뷰]
  P -->|"아니오, 인증됨"| F1[403]
  P -->|"아니오, 인증 정보 없음"| W{"첫 인증 클래스"}
  W -->|"WWW-Authenticate를 줌 (Token · Basic)"| E401[401]
  W -->|"못 줌 (Session)"| F2[403]

브라우저 탐색 화면에서 로그인하려면 URLconf에 api-auth/를 추가한다. 스프링에서 같은 역할은 필터체인과 @PreAuthorize가 나눠 맡는다.

출처: DRF Authentication: How authentication is determined · TokenAuthentication · DRF Permissions: Object level permissions · Custom permissions

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • DRF 파서·렌더러와 콘텐츠 협상

    DRF에서 파서(Parser)는 요청 본문을 파이썬 자료형으로 바꾸고, 렌더러(Renderer)는 응답 데이터를 클라이언트가 받을 형식으로 바꾼다. 어떤 렌더러를 쓸지는 요청의 Accept 헤더를 보고 고르는데, 이를 콘텐츠 협상(content negotiation)이라 한다.

  • CSRF

    CSRF(Cross-Site Request Forgery, 사이트 간 요청 위조)는 로그인한 사용자가 악성 사이트를 방문했을 때, 그 사이트가 사용자의 브라우저를 시켜 사용자 모르게 원래 사이트에 요청을 보내게 하는 공격이다. 공격자는 토큰을 훔치지 않는다. 브라우저가 쿠키를 알아서 붙여 준다는 점을 이용한다.

  • DRF 시리얼라이저

    DRF(Django REST Framework)의 시리얼라이저는 모델 인스턴스·QuerySet을 JSON으로 바꿀 수 있는 파이썬 기본 자료형으로 바꾸고(직렬화, serialization), 반대로 들어온 데이터를 검증해 모델로 만드는(역직렬화, deserialization) 틀이다. 장고의 Form과 비슷하게 필드와 검증 규칙을 선언한다.

  • Django 미들웨어와 로그인 흐름

    Django 미들웨어는 모든 요청과 응답을 감싸는 훅 체인(hook chain)이다. settings.MIDDLEWARE에 적힌 순서대로 요청이 들어가고, 응답은 그 역순으로 나온다. 세션 로드, CSRF 검사, 사용자 식별 같은 공통 처리가 여기서 일어난다.

  • DRF 필터·검색·정렬

    DRF의 목록 API는 쿼리 파라미터로 결과를 좁히는 세 가지 장치를 붙일 수 있다. 값이 정확히 맞는 것만 고르는 필터, 일부 문자열로 찾는 검색, 순서를 바꾸는 정렬이다. 모두 제네릭 뷰(GenericAPIView 계열)의 filter_backends로 적용된다.

보기 옵션