기존의 모델은 클래스 상속 없이 작성됐다.
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
를 온통 발라놨다.
그리고 후반부가 되어서야
'이야 이거 진짜 어떡하나' 이런 생각이 들었다.
django에서 제공하는 보안 기능 속에서 사용자에 대한 인증(Auth)이 이뤄지고 해당 사용자가 가질 권한(permission)에 대해서도 생각해봐야 했다.
그래서 AbstractBaseUser
또는 AbstractUser
를 상속해서 써야겠단 생각을 했다.
특징
언제 사용?
이 클래스를 상속하면 단 두개의 필드를 받게 된다.
스키마에 큰 영향을 준다는 것이 아마도 $ migrate
수행 시, 기존에 생성되어 있던 auth_user 그룹과 충돌이 일어나고 이걸 해결하기 위한 효과적인 방법이 없어서가 아닐까 싶다.
특징
settings.py
에 AUTH_USER_MODEL = '앱이름.유저모델이름'
과 같이 참조 작업이 필요하다.❗️
'앱이름.유저모델이름'
을 입력할 때 반드시 따옴표로 묶어줘야 한다
언제 사용?
읽어보면 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.py
에 AUTH_USER_MODEL
을 추가해주는 것이다.
나는 user앱의 models.py에 User라는 이름으로 AbstractUser를 상속했으므로 AUTH_USER_MODEL = 'user.User'
라고 적어줬다.
글로 구구절절 적어놔서 길게 보일 수 있지만
1. AbstractUser
상속
2. settings.py
에 AUTH_USER_MODEL='앱이름.모델이름'
알려주기
이게 끝이다. 정말 간단하다.
이렇게'만' 해주는 것으로도 @csrf_exempt
를 남발하는 참사를 막을 수 있다.
@csrf_exempt
는 이제 없다.😎 기능도 정상적으로 작동한다.
@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
파이썬 데코레이터란? 사용방법은?