-
[DRF - User] 커스텀 User -1한이음 프로젝트 2023. 8. 21. 15:27
Django는 일반적으로 User Model를 기본적으로 제공합니다. 하지만 대부분 이를 재구성을 합니다.
이것을 재구성하는 법을 작성할 예정입니다.
- BaseUserManger
- User Model 작성
- User Model에 jwt 적용
1. BaseUserManger
Django에서는 커스텀 유저를 정의하기 위해서는 UserManger Class가 필요합니다.
BaseUserManager를 상속받아, create_user함수를 재정의 후, User Model에서 BaseUserManager를 상속받아 사용하겠습니다.
BaseUserManager는 User를 생성시 사용하는 헬퍼 클래스입니다. User를 생성할때는 User date가 BaseUserManger를 거쳐 생성됩니다. create_user,create_superuser 함수를 정의하겠습니다.
create_user 함수는 관리자를 포함한 모든 사용자를 생성할때 실행되는 함수입니다.
create_superuser함수는 관리자를 생성할 때 실행되는 함수입니다.
class UserManager(BaseUserManager): def create_user(self,user_id, password, email, **extra_fields): if user_id is None: raise TypeError('아이디를 입력해주세요.') if email is None: raise TypeError('이메일을 입력해주세요.') if password is None: raise TypeError('비밀번호를 입력해주세요.') extra_fields.pop('password_check', None) user = self.model( user_id = user_id, email = self.normalize_email(email), **extra_fields ) # django 에서 제공하는 password 설정 함수 user.set_password(password) user.save() return user # admin user def create_superuser(self, user_id, password, email, **extra_fields): if password is None: raise TypeError('Superuser must have a password.') extra_fields.pop('password_check', None) # "create_user"함수를 이용해 우선 사용자를 DB에 저장 user = self.create_user(user_id, password, email, **extra_fields) # 관리자로 지정 user.is_superuser = True user.is_staff = True user.save() return user
2. User Model
User Model을 만들 것인데, user_id를 ID로 둘 것이며, 로그인 할때, user_id와 password를 통해 접속할 수 있도록 할 예정입니다.
class User(AbstractBaseUser, PermissionsMixin): userIdx = models.AutoField(primary_key=True) username = models.TextField( null=False, blank=True) user_id = models.TextField(max_length=30, unique=True, null=False, blank=False) password = models.TextField( null=False, blank=True) email = models.TextField( unique=True,null=False, blank=True) phone = models.TextField( unique=True,null=False, blank=True) last_login = models.DateTimeField(blank=True, null=True, verbose_name='last login') is_superuser = models.BooleanField(default=False) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True, blank=True) updated_at = models.DateTimeField(auto_now = True, blank=True) USERNAME_FIELD = 'user_id' #superuser만들떄 필요한 필드 REQUIRED_FIELDS = [ 'username', 'phone', 'email' ] # 헬퍼 클래스 사용 objects = UserManager() @property def token(self): return self._generate_jwt_token( ) def _generate_jwt_token(self): dt = datetime.now( ) + timedelta(days=60) token = jwt.encode({ 'userIdx': self.pk, 'exp': dt.utcfromtimestamp(dt.timestamp()) }, settings.SECRET_KEY, algorithm='HS256') return token
AbstractBaseUser 모델을 상속한 커스템 모델을 만들면 로그인 아이디로 이메일 주소를 사용하게 되는데
저는 user_id로 아이디를 사용할 것이여서, USERNAME_FIELD = 'user_id' 를 선언해주었습니다.
- USERNAME_FIELD
- USERNAME_FIELD 로 지정된 값을 흔히 말하는 로그인 ID로 사용합니다. - REQUIRED_FILEDS
- 필수로 값을 받아야 하는 필드를 명시합니다. - objects
- 앞서 정의한 UserManager를 입력해줍니다.
3. User Model에 jwt 적용
일단 jwt를 적용하기 위해서는
pip install pyjwt
@property def token(self): return self._generate_jwt_token( ) def _generate_jwt_token(self): dt = datetime.now( ) + timedelta(days=60) token = jwt.encode({ 'userIdx': self.pk, 'exp': dt.utcfromtimestamp(dt.timestamp()) }, settings.SECRET_KEY, algorithm='HS256') return token
이를 user mdoel 밑에 작성한다.
settings은
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_extensions', # 생성한 앱 'user', # 설치한 라이브러리 'rest_framework', 'rest_framework_simplejwt', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ), 'EXCEPTION_HANDLER': 'user.exceptions.core_exception_handler', 'NON_FIELD_ERRORS_KEY': 'error', } # 추가적인 JWT_AUTH 설정 SIMPLE_JWT = { 'ACCESS_TOKEN_LIFETIME': timedelta(minutes=30), 'REFRESH_TOKEN_LIFETIME': timedelta(days=7), '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': 'userIdx', 'USER_ID_CLAIM': 'userIdx', '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), }
자세한 settings 설정은 아래 공식문서를 확인해보길 바랍니다.
참고문헌
[# DRF Project_User] 2. Custom User model(커스텀 User) (tistory.com)
'한이음 프로젝트' 카테고리의 다른 글
[DRF- User& sms인증] 아이디 찾기 (0) 2023.09.12 [DRF - SMS] 네이버 SMS 문자 인증 구현하기 (1) 2023.09.05 [DRF - User] 로그인 API (0) 2023.08.21 [DRF - User] 회원가입 API (0) 2023.08.21 DRF 공부( python) (0) 2023.07.31