r잡초처럼
바른 프로그래밍
r잡초처럼
전체 방문자
오늘
어제
  • 분류 전체보기 (124)
    • FastAPI (7)
    • 끄적끄적 (2)
    • Python (17)
    • Django (31)
    • Database (2)
    • Docker (7)
    • 디자인패턴 (2)
    • CS 공부 (12)
      • 알고리즘 (2)
      • 자료 구조 (1)
      • 네트워크 (7)
      • IT 지식 (1)
      • 운영체제 (1)
    • 기타 팁들 (10)
    • Aws (2)
    • 독서 (1)
    • 코딩테스트 공부 (1)
      • 백준 (0)
      • 프로그래머스 (1)
    • DevOps (13)
    • TIL (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 모두의 네트워크
  • fastapi
  • 5장 회사에서 하는 랜 구성
  • preonboarding
  • 컴퓨터 기본 지식
  • CS 지식
  • poetry
  • 상속과 컴포지션
  • 파이썬 클린 코드
  • 상속 안티 패턴
  • 물리 계층
  • 6장
  • 완벽한 IT 인프라 구축을 위한 Docker
  • 책 리뷰
  • 7장
  • dotenv
  • 케이블의 종류
  • query param
  • validate
  • Batch
  • 랜과 왠
  • docker
  • pycharm
  • depends
  • encoding
  • 전기 신호
  • 랜 카드
  • cp949
  • pytest
  • 네트워크

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
r잡초처럼

바른 프로그래밍

Django

인증 구현하기

2023. 5. 14. 11:41

Django 인증 절차를 Custom 하고 싶었다.

나는 모든 View에서 인증 절차를 처리하는 AuthenticationMiddleware를 조작하거나 AUTHENTICATION_CLASSES를 재정의해서 request.user를 확인하는 절차를 처리할 수 있다. 나는 AuthenticationMiddleware 보다는 AUTHENTICATION_CLASSES 를 재정의하고자 했다. 그 이유는 AuthenticationMiddleware는 상위의 위치하는 레이어이기 때문에 이걸 섣부르게 커스텀했다가는 내가 인지 못하는 부작용이 발생할 거 같았다.

AuthenticationMiddleware 

AuthenticationMiddleware 는 각 View에서 인증을 위한 절차를 검사하는 middleware이다. 여기서 만약 custom 하고 싶다면 process_header를 재정의하면 된다.

class AuthenticationMiddleware(MiddlewareMixin):
    def process_request(self, request):
        if not hasattr(request, "session"):
            raise ImproperlyConfigured(
                "The Django authentication middleware requires session "
                "middleware to be installed. Edit your MIDDLEWARE setting to "
                "insert "
                "'django.contrib.sessions.middleware.SessionMiddleware' before "
                "'django.contrib.auth.middleware.AuthenticationMiddleware'."
            )
        request.user = SimpleLazyObject(lambda: get_user(request))

AUTHENTICATION_CLASSES 

내가 커스텀하고자 했던 인증 시스템은 Login 할 때 심어놓았던 cookie 를 백엔드 서버에서 읽어 들여 인증을 거치고자 했다. 굳이 프런트에서 인증 헤더에 심지 않고 백엔드에서 모두 처리하려고 했던 이유는 다음과 같았다. 

  1. 어차피 프론트에서도 cookie 값을 읽어 들여 헤더에 token을 심어서 보내는데, 백엔드에서 하면 프런트 쪽에서 할 일이 줄어들 거 같다.
  2. 보안적인 측면에서도 브라우에서 header 를 조작해 봤자 백엔드는 cookie를 바라보고 있기 때문에 header를 조작하는 것은 의미가 없다.

이러한 이유로 백엔드에서 cookie 를 통한 로그인 기능을 구현하고자 했다. 

우선 login 을 할 때 cookie에서 옵션을 통해 브라우저에서 조작할 수 없도록 했다.

response.set_cookie(
    domain="example.com",
    maxage=60 * 60,
    secure="True",
    samesite="Lax",
    httponly=True,
)

그리고 JWTAuthentication 를 상속받은 다음 커스텀 했다. JWTAuthentication에서는 authenticate 메서드에서 header를 읽어 들이고 있으므로 이 부분을 고쳤다.

  • 원래의 JWTAuthentication:
# JWTAuthentication


class JWTAuthentication(authentication.BaseAuthentication):
    """
    An authentication plugin that authenticates requests through a JSON web
    token provided in a request header.
    """

   ...
   
    def authenticate(self, request):
        header = self.get_header(request)
        if header is None:
            return None

        raw_token = self.get_raw_token(header)
        if raw_token is None:
            return None

        validated_token = self.get_validated_token(raw_token)

        return self.get_user(validated_token), validated_token
  • 커스텀:
class CustomJWTAuthentication(JWTAuthentication):
    def get_cookie(self, request):
        # 이 부분에서 cookie 를 읽어들이도록 만들었다.

    def authenticate(self, request):
        cookie = self.get_cookie(request)
        if cookie is None:
            return None

        raw_token = self.get_raw_token(cookie)
        if raw_token is None:
            return None

        validated_token = self.get_validated_token(raw_token)

        return self.get_user(validated_token), validated_token

커스텀을 하면서 errorMessage 도 사내 컨벤션에 따라 넣고자 했다.

    ...
    def get_validated_token(self, raw_token):
        ...
        raise InvalidToken(
            {
                "code": self.ERROR_CODE.FAIL_TOKEN_AUTH.code,  # 새롭게 커스텀한 부분
                "message": self.ERROR_CODE.FAIL_TOKEN_AUTH.message,  # 새롭게 커스텀한 부분
                "detail": {
                    "info": _(
                        "Given token not valid for any token type",
                    ),
                    "messages": messages,
                },
            }
        )

이렇게 인증 기능을 커스텀하면서 Django 의 middleware와 인증 기능을 이해하는 좋은 기회가 되었다.

'Django' 카테고리의 다른 글

[Django] - 사용자 로그인 - JWT 적용하기 - 2. JWT 이해하기  (0) 2023.07.03
사용자 로그인 - JWT 적용하기 - 1. Session 이해하기  (0) 2023.07.02
Django Channels - 채팅 기능 구현하기 - 1  (0) 2023.05.08
Django Channels - Consumer 살펴보기  (0) 2023.05.05
WebSocket 살펴보기 - 2  (0) 2023.05.05
    'Django' 카테고리의 다른 글
    • [Django] - 사용자 로그인 - JWT 적용하기 - 2. JWT 이해하기
    • 사용자 로그인 - JWT 적용하기 - 1. Session 이해하기
    • Django Channels - 채팅 기능 구현하기 - 1
    • Django Channels - Consumer 살펴보기
    r잡초처럼
    r잡초처럼
    오늘보다 내일 더 나은 개발자가 되기 위한 노력을 기록하는 블로그 입니다.

    티스토리툴바