커스텀 유저 구현
커스텀 유저를 구현하기 위해 공식 문서를 참고하여 코드를 구현해보자.
공식 문서에는 email 주소와 생년월일을 필수로 기입하도록 설정되었지만,
생년월일을 빼고 email 주소로 회원가입을 하고 로그인을 할 수 있도록 구현해 볼 것 이다.
https://docs.djangoproject.com/en/4.1/topics/auth/customizing/
Customizing authentication in Django | Django documentation | Django
Django The web framework for perfectionists with deadlines. Toggle theme (current theme: auto) Toggle theme (current theme: light) Toggle theme (current theme: dark) Toggle Light / Dark / Auto color theme Overview Download Documentation News Community Code
docs.djangoproject.com
BaseUserManager의 normalize_email을 통해 이메일 주소의 도메인 부분을 소문자로 지정하여 이메일 주소를 정규화하고 user.set_password를 통해 암호 해싱을 처리하면서 사용자의 암호를 주어진 원시 문자열로 설정한다.
그렇게 일반 유저와 관리자 유저를 생성할 수 있도록 UserManager 클래스를 생성해주고
# models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
class UserManager(BaseUserManager):
def create_user(self, email, password=None):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
)
# normalize_email : 이메일 주소를 정규화
user.set_password(password)
user.save(using=self._db)
return user
# 패스워드를 해싱하여 user_db에 저장
def create_superuser(self, email, password=None):
user = self.create_user(
email,
password=password,
)
user.is_admin = True
user.save(using=self._db)
return user
EmailField 값을 지정해주고 unique=True로 지정해주어 고유 식별자로 사용할 수 있도록 정의해준다.
is_active와 is_admin은 장고의 유저 모델의 필수 필드로 is_active는 사용자가 "활성"으로 간주되는지 여부를 나타내는 BooleanField이다.
USERNAME_FIELD = 'email' 사용자의 username field에 email을 사용하도록 설정해준다
# models.py
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
# 사용자의 username field에 email을 사용하도록 설정
REQUIRED_FIELDS = []
# 필수로 작성되어야 하는 field
def __str__(self):
return self.email
@property
def is_staff(self):
return self.is_admin
# 관리자 화면에 로그인 가능 여부
User 모델을 기반으로 serializer를 작성해주고 field로는 __all__ 모든 값을 설정해준다. create 시(회원가입 시) 입력 받은 데이터를 검중해주어야 하기 때문에 validated_data(유효성 검증을 통과한 값)를 기반으로 User 객체를 생성해준다.
simple-jwt 방식으로 토큰인증방식을 사용하여 TokenObtainPairSerializer를 사용하여 토큰 값을 생성할 수 있도록 한다.
# serializer.py
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework import serializers
from users.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
def create(self, validated_data):
user = super().create(validated_data)
user.set_password(user.password)
user.save()
return user
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['email'] = user.email
return token
simple-jwt의 토큰인증방식을 사용하는 방법에 대해서는 공식 문서를 통해 참조.
https://django-rest-framework-simplejwt.readthedocs.io/en/latest/customizing_token_claims.html
Customizing token claims — Simple JWT 5.2.1.post3+gbd4c6ce documentation
Customizing token claims If you wish to customize the claims contained in web tokens which are generated by the TokenObtainPairView and TokenObtainSlidingView views, create a subclass for the desired view as well as a subclass for its corresponding seriali
django-rest-framework-simplejwt.readthedocs.io
APIView 클래스를 이용하여 post 메소드를 구현하여 serializer를 통해 객체화하여 DB에 데이터를 저장할 수 있도록 한다.
# views.py
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from rest_framework_simplejwt.views import TokenObtainPairView
from users.serializers import UserSerializer, CustomTokenObtainPairSerializer
class UserView(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({"message": "회원 가입이 완료되었습니다"}, status=status.HTTP_201_CREATED)
else:
return Response({"message":f"%{serializer.errors}"}, status=status.HTTP_400_BAD_REQUEST)
class CustomTokenObtainPairView(TokenObtainPairView):
serializer_class = CustomTokenObtainPairSerializer
access token의 payload 수정 방법
회원가입과 로그인을 구현하여 포스트맨으로 POST로 JSON형식으로 회원가입을 한 다음 로그인을 하면 access 토큰을 받을 수 있는데, 토큰에는 여러 정보가 담겨 있고 access 토큰에 담겨있는 정보를 확인하기 위해서 jwt.io에 접속하여 access토큰 값을 입력하면 Decoded의 PAYLOAD에 토큰의 정보가 출력된다.
{
"email": "test@test.com",
"password": "qwer1234"
}
JWT.IO
JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
jwt.io
PAYLOAD에 토큰의 정보을 수정하기 위해서는 아래와 같이 serializer.py에서 token['email']을 통해 토큰의 정보를 추가하거나 수정할 수 있다.
# serializer.py
class CustomTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['email'] = user.email
token['token_message'] = "test"
return token
'코딩공부 > Django' 카테고리의 다른 글
Django Queryset, 데이터베이스에서 원하는 데이터 조회 (0) | 2022.11.15 |
---|---|
DRF Permission으로 사용자의 접근 제어 (0) | 2022.11.14 |
DRF Feedview 헤쳐보기 / TIL_221027 (0) | 2022.10.27 |
DRF JWT, CORS 란? / TIL_221026 (0) | 2022.10.26 |
Django 이미지 업로드 기능 구현 / TIL_221018 (0) | 2022.10.18 |
댓글