PROJECTS

DRF에서 JWT 사용하기

nicesugi 2022. 6. 30. 01:35

django, djangorestframework 가 설치되어있는 상태에서 진행해야 함

⭐️ simplejwt

pip install djangorestframework-simplejwt

# settings.py 
# 앱 추가
INSTALLED_APPS = [
    ...
    'rest_framework_simplejwt',
    ...
]

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

# 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'),
    ...
]

 

위의 코드 몇 줄로 simplejwt를 바로 테스트 할 수 있다!

user/urls.py 에 등록한 'api/token/'으로 아이디와 비밀번호를 담아 보내보면 refresh 토큰과 access 토큰값이 나올 것이다.

simplejwt  테스트

⭐️ 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 커스텀 클레임

payload에 id와 username을 추가

#jwt_claim_serializer.py 생성 후 작성
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
...
from user.jwt_claim_serializer import SpartaTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
...

class SpartaTokenObtainPairView(TokenObtainPairView):
    serializer_class = SpartaTokenObtainPairSerializer

# user/urls.py
...
from user.views import SpartaTokenObtainPairView
...

urlpatterns = [
    ...
    path('api/sparta/token/', SpartaTokenObtainPairView.as_view(), name='sparta_token'),
	...
]

⭐️ jwt 옵션 설정

 

커스텀 jwt 확인

⭐️ Access Token

JWT를 이용해 인증된 사용자만 접근할 수 있음 = 유효한 access 토큰을 가진 사용자라면, 인가된 사용자만 볼 수 있는 정보를 확인함

긴 시간동안은 안되고 5~20분 정도가 적당합니다.

# user/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()),
    ...
]

서버에 인가 확인을 하기 위해 headers에 access토큰값을

user/api/authonly/에 요청해보고 승인 됐을때와 승인 실패 됐을때를 비교해봅시당

좌- 승인 / 우 - 승인실패

⭐️ Refresh Token

토큰의 유효기간이 끝나면 재로그인을 하지 않고도 새롭게 access 토큰을 받아낼 수 있습니다

그게 바로 refresh 토큰.

refresh 토큰을 body에  넣어 서버에게 새로운 access토큰을 받는 루틴으로 인증/인가 과정을 구현합니다!

Refresh Token

 

반응형