장고 심화: Django Rest Framework 를 공부하자 2 - User, JWT 토큰 인증

r5z Yoon·2022년 10월 26일

사용자의 정보가 담겨있는 토큰을 주고받는 형식 > 쿠키가 아닌 로컬스토리지에 저장
참고. local storage vs cookies?

여기서 우리는 유저를 인증하고 식별하기 위한 JWT(Json Web Token)을 사용하여 RESTful 환경에서 사용자 데이터를 주고받을 수 있게 된다.
JWT는 header, payload, signiture로 구성되어 있고, headerdpsms JWT에서 사용할 타입과 해시 알고리즘이 payload에는 서버에서 첨부한 사용자 권한 정보, 데이터가 signiture에는 해시함수를 적용하여 인코딩된 private key로 서명된 전자서명이 담겨있다. 참고


simplejwt를 설치하고,

$ pip install djangorestframework-simplejwt

JWT로 인증하기 위해 settings.pyrest_framework의 인증 방식과 INSTALLED_APPS'rest_framework_simplejwt'를 추가해준다.
또 JWT의 설정도 부여해줄 수 있음. 기본적으로는 access, refresh 토큰의 유효시간을 설정한다.

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

-----

INSTALLED_APPS = [
    ...
    'rest_framework_simplejwt',
    ...
]

-----

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),
}

simplejwt에서 제공하는 기본 JWT 인증을 사용하기 위해 users/ulrs.py에 토큰 발급 view를 추가

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 클레임

토큰에 담긴 사용자의 정보를 의미하는 claim을 커스터마이징할 수도 있음.

user/serializer.py 생성 후

기본 토큰에는 user_id 만 반환 되는데, 여기에 원하는 클레임을 삽입한다.

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
    
# TokenObtainPairSerializer를 상속하여 클레임 설정
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
    @classmethod 
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        
        return token

user/views.py

Serializer는 위에서 만든 CustomTokenObtainPairSerializer 클래스를 그대로 serializer_class 에 지정한다.

...
from user.jwt_claim_serializer import 
CustomTokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
    ...

class CustomTokenObtainPairView(TokenObtainPairView):
	serializer_class = CustomTokenObtainPairSerializer

user/urls.pyCustomTokenObtainPairSerializer를 등록하여 응답할 수 있게 한다.

...
from user.views import CustomTokenObtainPairView
...

urlpatterns = [
    ...
    path('api/token/', views.CustomTokenObtainPairView.as_view(), name='token_obtain_pair'),
		...
]



날도 건조하고 모니터 보는 시간도 절대적으로 늘어서 매일 눈이 너무 아프당... 주말에 하루 정도는 절대로 모니터 안 볼 계획을 내심 세우고 있었는데 이 속도면 그게 되겠나.. 싶다.
캠프 절반쯤 되어가니 역시 결국 내가 하고 싶은 일이 웹 개발이 아닌 건 너무 잘 알겠다.
데이터 공부도 해야겠다 생각은 하는데, 병행은 정말 꿈도 못 꾸겠고 멀라.. again 난 내 길을 갈게... 내 속도로..

profile
_____ is a process </br> https://github.com/R5Z

0개의 댓글