Django JWT 인증 시스템 직접 구현하기

GisangLee·2022년 2월 24일
1

my_module

목록 보기
4/33
post-custom-banner

Django의 JWT는 주로 simple jwt를 쓴다.

하지만 나는 pyJwt만으로 모든 인증 시스템을 직접 구축할 것이다.

  • 왜 WHY? > 난 내가 직접 커스텀 하는 걸 선호한다.

패키지 설치

$ pip install pyjwt
  • jwt_token.py
import os, jwt, datetime, time

# JWT 발급 시스템
def generate_jwt_token(payload, type):
    SECONDS = 1
    MINUTE = SECONDS * 60
    HOUR = MINUTE * 60
    DAY = HOUR * 24
    MONTH = DAY * 30
    YEAR = DAY * 365

    if type == "access":
        #exp = datetime.datetime.now() + datetime.timedelta(seconds=3)
        # 만료 토큰 생명 주기 한 달
        exp = int(time.time()) + (MONTH)

    elif type == "refresh":
        # 갱신 토큰 생명 주기 한 달 + 1주
        exp = int(time.time()) + (MONTH + (DAY * 7))

    else:
        raise Exception("토큰 타입을 정확하게 명시해 주세요.")

    payload["exp"] = exp
    payload["iat"] = datetime.datetime.now()
    jwt_encoded = jwt.encode(payload, os.environ.get("DJANGO_SECRET_KEY"), algorithm=os.environ.get("JWT_ALGORITHM"))

    return jwt_encoded

토큰 인증 시스템

  • token_auth.py
import os, jwt, time, datetime
from django.contrib.auth import get_user_model
from rest_framework import exceptions

JWT_SECRET = os.environ.get("DJANGO_SECRET_KEY")
ALGORITHM = os.environ.get("JWT_ALGORITHM")

user_model = get_user_model()

def get_authorization_header(request):
    auth = request.META.get("HTTP_AUTHORIZATION")
    system_key = request.META.get("HTTP_SYSTEM_KEY")
    return [auth, system_key]


class CustomJwtTokenAuthentication():	
	keyword = "jwt"
    
    def authenticate(self, request):
        token = get_authorization_header(request)
        print(f"TOKEN : {token}")
        
        if not token or not system_key or ( system_key != os.environ.get("HTTP_SYSTEM_KEY")):
            raise exceptions.AuthenticationFailed("시스템 키가 없거나 사용자를 인증할 수 없습니다.")
        
        token = token.replace("jwt ", "")
        
        # 토큰 디코딩
        payload = jwt.decode(token, JWT_SECRET, algorithms=[ALGORITHM])

        # 토큰 만료 데이터 파싱
        expire = payload.get("exp")

        # 현재 시간
        cur_date = int(time.time())
        
        # 토큰 만료 처리
        if cur_date > expire:
            return None
        
        # 유저 객체
        user_id = payload.get("user_id")

        if not user_id:
            return None
        
        try:
            user = user_model.objects.get(pk=user_id)
        except user_model.DoesNotExist:
            raise exceptions.AuthenticationFailed("사용자가 존재하지 않습니다.")
        
        return (user, token)
        
    def authenticate_header(self, request):
        return self.keyword

커스텀한 토큰 인증 시스템 붙이기

  • settings.py
# DRF 세팅
REST_FRAMEWORK = {
    #"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated",],
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.AllowAny",),
    "DEFAULT_AUTHENTICATION_CLASSES": [
        'accounts.token_auth.CustomJwtTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ],
}

이제 Django는 내가 만든 커스텀 JWT 인증 시스템을 활용할 것이고

JWT 발급부터 만료 등 모든 것을 컨트롤 할 수 있게 되었다.

아주 간단하구만

profile
포폴 및 이력서 : https://gisanglee.github.io/web-porfolio/
post-custom-banner

0개의 댓글