[ 06/28 TIL ] django에서 jwt 사용하기

JoonQpa·2022년 6월 28일
1

TIL

목록 보기
23/27
post-thumbnail
post-custom-banner

DRF에서 JWT 사용하기

simplejwt 를 설치합니다. 기존 djangorestframework-jwt는 더이상 업데이트가 되고 있지 않습니다.

$ pip install djangorestframework-simplejwt

JWT로 인증할 것 이기 때문에 settings.pyREST_FRAMEWORK의 인증 방식을 변경(추가)해 줍니다.

  • settings.py
    'DEFAULT_AUTHENTICATION_CLASSES': [
    		...
    		# JWT 인증 방식 추가하기
    		'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],

simplejwt 에서 제공하는 기본 JWT 인증을 사용할 것입니다. 따라서 인증 토큰 발급 urlpatterns 에 토큰 발급 view 를 추가해 줍니다.

  • user/urls.py
    from rest_framework_simplejwt.views import (
        TokenObtainPairView,
        TokenRefreshView,
    )
    
    urlpatterns = [
        ...
        path('api/token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
        path('api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
        ...
    ]

JWT를 사용하기 위해 INSTALLED_APPS'rest_framework_simplejwt' 추가해 줍니다.

  • drf_jwt/settings.py
    INSTALLED_APPS = [
        ...
        'rest_framework_simplejwt',
        ...
    ]

JWT 옵션 설정하기

settings.py에서 JWT에 대한 설정을 부여할 수 있습니다. 기본적으로는 access 토큰과 refresh 토큰의 유효시간을 설정합니다.

  • drf_jwt/settings.py
    from datetime import timedelta
    ...
    
    SIMPLE_JWT = {
    		# Access 토큰 유효 시간 설정하기
        'ACCESS_TOKEN_LIFETIME': timedelta(minutes=5),
    		# Refresh 토큰 유효 시간 설정하기
        'REFRESH_TOKEN_LIFETIME': timedelta(days=1),
    
        'ROTATE_REFRESH_TOKENS': False,
        'BLACKLIST_AFTER_ROTATION': False,
        'UPDATE_LAST_LOGIN': False,
    
        'ALGORITHM': 'HS256',
        'SIGNING_KEY': SECRET_KEY,
        'VERIFYING_KEY': None,
        'AUDIENCE': None,
        'ISSUER': None,
        'JWK_URL': None,
        'LEEWAY': 0,
    
        **'AUTH_HEADER_TYPES': ('Bearer',),
        'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
        'USER_ID_FIELD': 'id',
        'USER_ID_CLAIM': 'user_id',
        'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',**
    
        'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
        'TOKEN_TYPE_CLAIM': 'token_type',
        'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
    
        'JTI_CLAIM': 'jti',
    
        'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
        'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
        'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
    }

커스텀 JWT 클레임

토큰에 담긴 사용자의 정보를 의미하는 claim 을 커스터마이징할 수도 있습니다. Serializer 를 활용하여 simplejwt 에서 제공하는 기본 정보 이외에 우리가 포함하고 싶은 정보를 토큰에 추가적으로 넣어봅니다.

  • user/jwt_claim_serializer.py 생성 후 작성. 기본 토큰에는 user_id 만 반환 되는 것을 알 수 있는데요, 여기에 id , username 클레임을 같이 삽입해 보겠습니다.
    from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    
    # TokenObtainPairSerializer를 상속하여 클레임 설정
    class SpartaTokenObtainPairSerializer(TokenObtainPairSerializer):
        @classmethod
        def get_token(cls, user):
    				# 생성된 토큰 가져오기
            token = super().get_token(user)
    
            # 사용자 지정 클레임 설정하기.
            token['id'] = user.id
            token['username'] = user.username
    
            return token
  • user/views.py Serializer 구현은 매우 간단합니다. 위에서 만든 SpartaTokenObtainPairSerializer 클래스를 그대로 serializer_class 에 지정하겠습니다.
    ...
    from user.jwt_claim_serializer import SpartaTokenObtainPairSerializer
    from rest_framework_simplejwt.views import TokenObtainPairView
    ...
    
    class SpartaTokenObtainPairView(TokenObtainPairView):
        serializer_class = SpartaTokenObtainPairSerializer
  • user/urls.py urlpatternsSpartaTokenObtainPairView 를 등록하여 응답할 수 있게 합니다.
    ...
    from user.views import SpartaTokenObtainPairView
    ...
    
    urlpatterns = [
        ...
        path('api/sparta/token/', SpartaTokenObtainPairView.as_view(), name='sparta_token'),
    		...
    ]

Access Token

이번엔 JWT를 이용해 인증된 사용자만 접근할 수 있는 view 를 만들어 보겠습니다. 유효한 access 토큰을 가진 사용자라면 인가된 사용자만 볼 수 있는 정보를 확인할 수 있습니다.

  • users/views.py
    ...
    from rest_framework_simplejwt.authentication import JWTAuthentication
    ...
    
    # 인가된 사용자만 접근할 수 있는 View 생성
    class OnlyAuthenticatedUserView(APIView):
        permission_classes = [permissions.IsAuthenticated]
    		
    		# JWT 인증방식 클래스 지정하기
    		authentication_classes = [JWTAuthentication]
    
        def get(self, request):
    				# Token에서 인증된 user만 가져온다.
            user = request.user
            print(f"user 정보 : {user}")
            if not user:
                return Response({"error": "접근 권한이 없습니다."}, status=status.HTTP_401_UNAUTHORIZED)
            return Response({"message": "Accepted"})
  • user/urls.py
    ...
    from user.views import OnlyAuthenticatedUserView
    ...
    urlpatterns = [
        ...
    		path('api/authonly/', OnlyAuthenticatedUserView.as_view()),
    		...
    ]
profile
Intuition factory: from noob to pro
post-custom-banner

0개의 댓글