AbstractUser model

0

장고 프로젝트

목록 보기
10/15
post-thumbnail

기존 모델

기존의 모델은 클래스 상속 없이 작성됐다.

class Account(models.Model):
    pid = models.CharField(max_length=30, null=True)
    pwd = models.CharField(max_length=30, null=True)
    created = models.DateTimeField(null=True, auto_now_add=True)


    def __str__(self):
        return "pid: "+self.pid

    class Meta:
        ordering = ['created']

계정(pid)과 비밀번호(pwd) 정보만을 받아서 저장했고, DateTimeField를 사용하여 생성날짜(created)를 알 수 있도록 했다.

$ python manage.py shell으로 ORM을 사용할 때, 객체가 저장하고 있는 정보를 알리기 위해 __str__함수를 정의해줬다.

정렬 순서(ordering)은 생성순(created)으로 정해줬다.

보안 문제

하지만 이렇게 해놓고 회원가입 기능을 사용하려고 할 때는 @csrf_exempt를 붙여줘야 했다.
이걸 붙여주지 않으면 아래와 같은 결과창을 볼 수 있다.


Forbidden(403) CSRF verification failed. Request aborted.

CSRF: Cross Site Request Forgery
통상적인 방법으로 인증을 받은 사용자가 가진 권한을 공격자가 이용하여 서버에 변조된 요청을 보내는 공격방식.

이를 막기 위해 django에서는 CSRF에 대응하는 기능을 제공한다.

헌데 내 경우에 이 기능에 대한 예외를 설정하지 않으면(@csrf_exempt를 데코레이팅하지 않으면) Forbidden을 구경할 수밖에 없었다.

기능을 사용하기 위해 보안벽을 떼놓는다는 게, 지금 다시 생각해보면 정말 말이 안 되는 짓이다.

하지만 프로젝트 진행 초기에는 그냥 앱에서 들어오는 정보들을 받아서 데이터베이스에 넣을 수 있다는 사실에 신명이 나서 @csrf_exempt를 온통 발라놨다.

그리고 후반부가 되어서야
'이야 이거 진짜 어떡하나' 이런 생각이 들었다.

User 모델의 사용

django에서 제공하는 보안 기능 속에서 사용자에 대한 인증(Auth)이 이뤄지고 해당 사용자가 가질 권한(permission)에 대해서도 생각해봐야 했다.

그래서 AbstractBaseUser 또는 AbstractUser를 상속해서 써야겠단 생각을 했다.

AbstractBaseUser

특징

  • 다루는 데 각별한 주의가 필요하다. AbstractBaseUser를 확장하여 model을 작성하는 것 데이터베이스 스키마에 큰 영향을 준다. 따라서 이 확장 작업은 프로젝트 초기에 수행해야 한다.

언제 사용?

  • 애플리케이션에 인증 프로세스와 관련된 특정 요구 사항이 있는 경우에 사용한다. 예를 들어, 어떤 경우에는 사용자 이름 대신 이메일 주소를 식별 토큰으로 사용하는 것이 더 합리적이다.

이 클래스를 상속하면 단 두개의 필드를 받게 된다.

  • 'password'와 'last_login'

스키마에 큰 영향을 준다는 것이 아마도 $ migrate 수행 시, 기존에 생성되어 있던 auth_user 그룹과 충돌이 일어나고 이걸 해결하기 위한 효과적인 방법이 없어서가 아닐까 싶다.

AbstractUser

특징

  • 마찬가지로 프로젝트 초기에 AbstractUser를 이용한 모델 확장 작업을 해주는 게 권장된다. 또한 settings.pyAUTH_USER_MODEL = '앱이름.유저모델이름'과 같이 참조 작업이 필요하다.

    ❗️ '앱이름.유저모델이름'을 입력할 때 반드시 따옴표로 묶어줘야 한다

언제 사용?

  • Django가 인증 프로세스를 처리하는 방식에 완벽하게 만족하고 아무 것도 변경하지 않을 때 사용한다. 그러면서도 추가 클래스를 만들 필요 없이 사용자 모델에 직접 추가 정보를 추가할 수도 있다.

읽어보면 AbstractUser를 쓰는게 상당히 좋아보였기에 이걸 써봤다.
(참고자료는 페이지 마지막에 링크)

class User(AbstractUser, PermissionsMixin):
    class Meta:
        ordering = ['date_joined']
    # username = models.CharField()
    # password = models.CharField()
    # last_login = models.DateTimeField(blank=True, null=True)
    # first_name = models.CharField(max_length=30, blank=True)
    # last_name = models.CharField(max_length=150, blank=True)
    # email = models.EmailField(blank=True)
    # is_staff = models.BooleanField()
    # is_active = models.BooleanField()
    # date_joined = models.DateTimeField()
    # is_superuser = models.BooleanField()

#주석처리된 부분이 AbstractUser 클래스를 상속했을 때 기본적으로 갖게 되는 필드들이다.

일단 난 username과 password만 필요했기 때문에 추가적으로 모델 정보를 작성하진 않았다. 그리고 username과 password라는 명칭을 바꾸기보단 안정적으로 그대로 사용하는 것을 택했다.

잊지 말아야 할 것은 위의 설명글에서처럼 settings.pyAUTH_USER_MODEL을 추가해주는 것이다.

나는 user앱의 models.py에 User라는 이름으로 AbstractUser를 상속했으므로 AUTH_USER_MODEL = 'user.User'라고 적어줬다.

글로 구구절절 적어놔서 길게 보일 수 있지만
1. AbstractUser 상속
2. settings.pyAUTH_USER_MODEL='앱이름.모델이름' 알려주기
이게 끝이다. 정말 간단하다.

이렇게'만' 해주는 것으로도 @csrf_exempt를 남발하는 참사를 막을 수 있다.

@csrf_exempt는 이제 없다.😎 기능도 정상적으로 작동한다.

데코레이터(decorator)와 래퍼(wrapper)에 대해서는 조금 더 정리가 필요해서 자세한 필기는 따로 할 것이다.

@api_view를 사용해보았다. @api_view를 써서 해당 view가 어떻게 작동하고 있는지 어떤 옵션을 가지고 있는지를 볼 수도 있고 해당 기능에 대한 테스트 작업도 해볼 수 있다!

다른 모델은 기존에 사용하던 방식과 동일하게 모델을 작성해줬다. 예를 들면 아래와 같은 코드다.

# 스쿼트 운동 관련 모델
class Squat(models.Model):
    username = models.CharField(max_length=25)

    count = models.FloatField(max_length=255)

    sum_times = models.IntegerField(null=True)
    sum_count = models.IntegerField(null=True)

    times = models.FloatField(max_length=255)
    title = models.CharField(max_length=255, null=True)
    day = models.CharField(max_length=255, null=True)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return "Count:"+str(self.count)+" Time:"+str(self.times)+" Date:"+self.day

    class Meta:
        ordering = ['created']

로그인 시에 필요한 계정명과 동일한 username으로 column이름을 사용했다. 다만 필드를 CharField로 설정하여 특정 계정의 기록을 불러올 때 사용할 수 있도록 해놓았다.

이 부분은 아마 permission을 설정할 때 따로 바꿔야할 수도 있겠다. 혹은 전체 DB 구성을 다시 작성해할 수도 있겠단 생각이 든다.😓

이렇게 해두면 아무나 권한 없이 특정 사용자의 이름으로 기록을 등록할 수 있게 되어버린다.

위 User모델에서 볼 수 있듯이 permissionMixin을 사용해보기 위해 상속해놓았다.

model에 대한 다음 공부 주제는 권한(permission)을 현재의 user모델에 연관짓는 것으로 할 것이다.


django user모델의 확장
[DJango] AbstractBaseUser vs AbstractUser 비교하기
Spring Security_CSRF Token의 개념과 사용 방법
Django Rest Framework 활용하기 2 - @api_view
파이썬 데코레이터란? 사용방법은?

0개의 댓글