노트

Django 미들웨어와 로그인 흐름

Django Middleware and Login Flow

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

쉽게 말하면

Django 미들웨어는 모든 요청이 지나가는 공항 출국 절차 같아요. 세션 확인, CSRF 검사, 사용자 확인을 정해진 순서대로 거쳐야 뷰에 닿으니, 공통 검사를 뷰마다 반복하지 않아도 되죠.

비유가 깨지는 곳 공항과 달리 응답도 같은 절차를 역순으로 거쳐 나와요. 순서도 의미가 있어서, 세션에서 사용자를 읽는 AuthenticationMiddleware는 SessionMiddleware 뒤에 와야 해요.

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

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",      # 세션 로드
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",                 # CSRF 검사
    "django.contrib.auth.middleware.AuthenticationMiddleware",   # request.user 채우기
    "django.contrib.messages.middleware.MessageMiddleware",
]

순서가 의미를 가진다. AuthenticationMiddleware는 세션에서 사용자를 읽으므로 SessionMiddleware 뒤에 와야 한다.

직접 만들기

class TimingMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
 
    def __call__(self, request):
        start = time.monotonic()
        response = self.get_response(request)          # 다음 미들웨어·뷰
        response["Server-Timing"] = f"app;dur={(time.monotonic() - start) * 1000:.0f}"
        return response

세션 로그인 흐름

POST /login (username, password, csrfmiddlewaretoken)
→ SessionMiddleware: 기존 세션 로드
→ CsrfViewMiddleware: 토큰 검증
→ LoginView.form_valid:
     authenticate() → AUTHENTICATION_BACKENDS를 차례로 시도(ModelBackend는 비밀번호 해시 비교)
     추가 검사(탈퇴·차단 계정 등)
     login(request, user) → 세션에 사용자 ID 저장, 세션 키 교체
→ 응답: 성공 시 리다이렉트, 실패 시 폼 오류와 함께 로그인 화면(JSON API로 직접 만들면 401 등)
  • login()은 로그인할 때 세션 키를 새로 발급해 세션 고정 공격(session fixation)을 막는다
  • 계정 상태에 따른 추가 규칙은 LoginView를 상속해 form_valid를 덮어쓰거나 커스텀 인증 백엔드로 넣는다
  • 비밀번호는 기본 PBKDF2(Password-Based Key Derivation Function 2)로 해시돼 있다(비밀번호 저장: 인코딩·암호화·해싱)

세션 저장과 만료는 세션 인증, CSRF 검사의 원리는 Django의 CSRF 방어, 인증과 인가의 구분은 인증과 인가를 본다. 스프링에서 같은 자리는 필터체인이 차지한다. 요청을 차례로 넘기는 구조는 책임 연쇄 패턴 패턴이다.

출처: Django 문서: Writing your own middleware · Middleware ordering · How to log a user in

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • CSRF

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

  • DRF 인증과 권한

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

  • DRF 필터·검색·정렬

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

  • DRF API 테스트

    DRF는 장고 테스트 위에 API 요청을 편하게 보내는 APITestCase와 APIClient를 제공한다. 장고 테스트 러너(test runner)는 테스트용 DB를 따로 만들고, 각 테스트를 트랜잭션으로 감싸 끝나면 되돌리므로 실제 데이터를 건드리지 않는다.

보기 옵션