메인 페이지에서 로그인 한 유저의 프로필 이미지를 띄워주기 위해 Access Token
에 프로필 이미지의 URL을 넣어주기 위한 작업을 진행했습니다.
from django.conf import settings
from rest_framework.exceptions import AuthenticationFailed
from rest_framework import serializers
from user.models import User, ProfileImage
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.validators import UniqueValidator
from django.contrib.auth.password_validation import validate_password
class LoginSerializer(TokenObtainPairSerializer):
"""DRF의 JWT 로그인 방식에 사용되는 TokenObtainPairSerializer를 상속하여 Serializer를 커스터마이징하여 재정의합니다."""
def validate(self, request_data):
print(request_data)
request_email = request_data.get('email')
request_password = request_data.get('password')
try:
user = User.objects.get(email=request_email)
except User.DoesNotExist:
raise AuthenticationFailed("사용자를 찾을 수 없습니다. 로그인 정보를 확인하세요.")
if not user.check_password(request_password):
raise AuthenticationFailed("비밀번호가 일치하지 않습니다.")
elif user.is_active == False:
raise AuthenticationFailed("이메일 인증이 필요합니다.")
token = super().get_token(user)
refresh = RefreshToken.for_user(user)
user_profile_img = ProfileImage.objects.get(owner=user)
token['profile_img'] = str(user_profile_img.profile_img)
return {
'access': str(token.access_token),
'refresh': str(refresh)
}
DRF의 토큰 객체는 JSON직렬화가 가능한 Python 기본 데이터 유형이 아닙니다. 그래서 DRF에서 JWT 토큰 로그인 방식을 사용할 경우 TokenObtainPairSerializer
에 정의된 validate
메서드에서 토큰 객체를 직렬화가 가능하도록 문자열 처리(str()
를 해줍니다.
class TokenObtainPairSerializer(TokenObtainSerializer):
token_class = RefreshToken
def validate(self, attrs: Dict[str, Any]) -> Dict[str, str]:
data = super().validate(attrs)
refresh = self.get_token(self.user)
data["refresh"] = str(refresh)
data["access"] = str(refresh.access_token)
if api_settings.UPDATE_LAST_LOGIN:
update_last_login(None, self.user)
return data
재정의한 LoginSerializer에서는 이 validate
메서드를 오버라이드 하고 있기 때문에 직접 토큰 객체들을 직렬화 가능한 데이터로 변환해줘야 합니다.
return {
'access': token.access_token,
'refresh': refresh
}
이렇게 그냥 반환하려고 한다면 TypeError: Object of type AccessToken is not JSON serializable
에러가 발생합니다.