ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [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 설정은 아래 공식문서를 확인해보길 바랍니다.

    Settings — Simple JWT 5.2.2.post30+gfaf92e8 documentation (django-rest-framework-simplejwt.readthedocs.io)

     

     

     

    참고문헌 

    [# 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
Designed by Tistory.