Post

Django: JWT를 이용한 Token Authentication 구현하기

Django REST Framework에서 JWT를 활용한 토큰 기반 인증 구현 가이드.

Django: JWT를 이용한 Token Authentication 구현하기

01. 시작하기 전에

프로젝트 설정

JWT 기반 인증을 구현하기 전에 Django 프로젝트에서 기본 설정을 진행해야 합니다. 이를 통해 사용자 정의 모델과 데이터베이스 시딩(seeding)을 설정합니다.

urls.py 설정

1
2
3
4
5
6
7
8
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path("api/v1/articles/", include("articles.urls")),
    path("api/v1/accounts/", include("accounts.urls")),
]

Custom User Model 생성 accounts/models.py에서 사용자 정의 모델을 생성합니다.

1
2
3
4
5
from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
    pass

Custom User 설정 settings.py에 사용자 정의 모델을 설정합니다.

1
AUTH_USER_MODEL = "accounts.User"

데이터베이스 초기화 및 시딩

  • 랜덤 모델에 50개의 데이터를 추가:
1
python manage.py seed articles --number=50
  • 특정 모델에 20개의 데이터를 추가 (조건 포함):
1
python manage.py seed articles --number=20 --seeder "Comment.article_id" 1

02. JSON Web Token, JWT

쿠키 (Cookie)

  • HTTP 요청과 응답에 포함되는 데이터 조각.
  • 도메인에 제한적이며, 유효 기간이 있음.

세션 (Session)

  • HTTP의 Stateless 특징을 보완하기 위한 방법.
  • 세션 ID를 쿠키에 저장하여 서버와 클라이언트 간 인증을 처리.

JSON Web Token, JWT

JWT는 세션 대신 토큰을 이용하여 인증을 처리합니다. 토큰 자체에 사용자 정보와 서명이 포함되어 있어 별도의 세션 DB 없이 인증을 처리할 수 있습니다.

JWT 처리 방식

  1. 클라이언트가 ID/PW를 서버로 전송.
  2. 서버가 ID/PW를 검증 후 토큰을 생성해 응답.
  3. 클라이언트는 요청 헤더에 토큰을 포함시켜 요청.
  4. 서버는 토큰의 유효성을 검증 후 요청을 처리.

세션과의 차이점

  • 세션 데이터베이스가 필요 없음.
  • 서버는 토큰의 유효성만 검증.
  • 인증 데이터가 토큰에 직접 포함됨.

JWT 구조 JWT는 Header, Payload, Signature 세 부분으로 구성됩니다.

  1. Header
    • 토큰 타입과 알고리즘 정보 포함.
    1
    2
    3
    4
    
    {
        "alg": "HS256",
        "typ": "JWT"
    }
    
  2. Payload
    • 사용자 정보와 클레임(Claims) 포함.
    1
    2
    3
    4
    5
    
    {
        "sub": "1234567890",
        "name": "John Doe",
        "admin": true
    }
    
  3. Signature
    • Header와 Payload를 비밀키로 서명하여 생성.

Access Token과 Refresh Token

Access Token

  • 클라이언트가 요청 시 사용하는 인증 토큰.
  • 보안상 유효 기간을 짧게 설정.

Refresh Token

  • Access Token 만료 시 새로운 Access Token 발급에 사용.
  • 클라이언트가 장기적으로 저장하며, 유효 기간이 더 길게 설정됨.

03. Django에 JWT 구현하기

라이브러리 설치

1
pip install djangorestframework djangorestframework-simplejwt

Django 설정

settings.py

1
2
3
4
5
6
7
8
9
10
11
INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework_simplejwt',
]

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "rest_framework_simplejwt.authentication.JWTAuthentication",
    ],
}

JWT 설정 커스터마이징

1
2
3
4
5
6
7
8
from datetime import timedelta

SIMPLE_JWT = {
    "ACCESS_TOKEN_LIFETIME": timedelta(minutes=30),
    "REFRESH_TOKEN_LIFETIME": timedelta(days=1),
    "ROTATE_REFRESH_TOKENS": True,
    "BLACKLIST_AFTER_ROTATION": True,
}

URL 설정

accounts/urls.py

1
2
3
4
5
6
7
from django.urls import path
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

urlpatterns = [
    path("signin/", TokenObtainPairView.as_view(), name="token_obtain_pair"),
    path("token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
]

04. 접근 제한하기

보호된 뷰 생성 views.py에서 인증이 필요한 API를 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated

class ArticleListAPIView(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid(raise_exception=True):
            serializer.save()
            return Response(serializer.data, status=201)

Token 전달

  • 클라이언트는 요청 시 Authorization 헤더에 Token을 포함해야 합니다.
1
Authorization: Bearer <your_access_token>

05. 테스트 및 검증

로그인 요청

  • 엔드포인트: /api/v1/accounts/signin/
  • 요청 JSON:
1
2
3
4
{
    "username": "admin",
    "password": "admin1234"
}
  • 응답:
1
2
3
4
{
    "access": "<access_token>",
    "refresh": "<refresh_token>"
}

보호된 API 요청

  • 엔드포인트: /api/v1/articles/
  • 헤더에 Access Token 포함:
1
Authorization: Bearer <access_token>
  • 만료된 Access Token은 Refresh Token을 사용하여 갱신합니다.

마무리

JWT를 사용하면 Django REST Framework에서 인증을 간편하고 효율적으로 처리할 수 있습니다. 그러나 보안 취약점을 보완하기 위해 HTTPS 사용, 토큰 관리, 짧은 유효 기간 설정 등을 고려해야 합니다.

This post is licensed under CC BY 4.0 by the author.