본문 바로가기

멋사 10기 졸업 프로젝트/정리

[django] password 암호화 : make_password, check_password

다른 사람이 작업한 user model을 pull해서 다시 user작업을 하게됐다.

모델 필드가 조금 바뀐 것 말고는 크게 바뀌지 않을 거라고 생각했는데 

AttributeError: 'User' object has no attribute 'set_password'  이런 오류가 생겼다.

이전에 나는 User model을 만들 때 장고의 AbstractUser model을 이용하여 만들었는데, 이 모델에는 password를 암호화 해주는 set_password가 있다. 하지만 지금은 모델을 직접 커스텀하기 때문에 이 함수를 사용할 수 없다.

 

 

#models.py

from django.db import models

class TimestampZone(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    deleted_at = models.DateTimeField(null=True)

    class Meta:
        abstract = True

class User(TimestampZone):
    username=models.CharField(max_length=200, unique=True, default='')
    password = models.CharField(max_length=200)
    nickname = models.CharField(max_length=100) #닉네임(유저 이름)
    url_value = models.CharField(max_length=2000, unique=True)

    def __str__(self):
        return self.username

 

그럼 직접 커스텀하는 모델은 어떻데 암호화를 할까?

 

 

 

 

 


회원가입

직접 커스텀된 모델의 암호를 해시화하여(암호화하여)저장하기 위해서는 make_password함수를 사용한다.

 

 

#serializers.py

from rest_framework import serializers
from accounts.models import User
from django.contrib.auth.hashers import make_password, check_password

from rest_framework_simplejwt.tokens import RefreshToken

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model=User
        fields=['id','username','password','nickname','created_at','updated_at','deleted_at','url_value']

    def create(self, validate_data):
        user=User.objects.create(
            nickname=validate_data['nickname'],
            username=validate_data['username'],
            url_value=validate_data['url_value'],
            password=make_password(validate_data['password']),
        )
        # user.set_password(validate_data['password'])
        token = RefreshToken.for_user(user)
        user.refreshtoken = token
        user.save()

        return user

이전의 set_password는 주석처리 해줬다.

from django.contrib.auth.hashers import make_password, check_password를 import해줘야 함수가 사용가능하다.

위와 같이 make_password를 사용하면 된다. 

참고로 작업할 때 validate_data를 적용하지 않고 password를 바로 함수를 적용해 저장했는데, 그럼 데이터가 잘못 저장된다. 뒤에 로그인 작업할때, 맞는 비밀번호를 입력해도 if 출력이 계속 false로 return한다...

 

 

 


로그인

암호화된 비밀번호를 가져오기 위해 check_password함수를 이용한다.

 

 

#serializers.py

class UserLoginSerializer(serializers.Serializer):
    username=serializers.CharField(max_length=64)
    password=serializers.CharField(max_length=64, write_only=True)

    def validate(self, data):
        username=data.get("username", None)
        password=data.get("password", None)


        if User.objects.filter(username=username).exists():
            user=User.objects.get(username=username)
            hashed_password=make_password('password')
            if not check_password(password, user.password):
                raise serializers.ValidationError("not id or password")
        else:
            raise serializers.ValidationError("User does not exist")

        token = RefreshToken.for_user(user=user)
            
        data = {
            'id': user.id,
            'nickname' : user.nickname,
            'url_value':user.url_value,
            'refresh_token' : str(token),
            'access_token' : str(token.access_token)
        }
        return data

check_password를 사용할 때 주의할 점은, 입력받은 비밀번호와 암호화되어 저장된 비밀번호, 즉 복호화할 유저의 비밀번호 두개의 인자를 넘겨야 한다.

그렇지 않으면 check_password() missing 1 required positional argument: 'encoded' 오류가 난다.

 

 

 

 


또, AUTH_USER_MODEL='app_name.model_name'또한 삭제 했다. 직접 커스텀한 유저 모델을 사용하면 필요 없음.

views.py는 따로 건드리지 않았다.

 

 

pull을 하고나서 models.py에서 TimestampZone모델은 처음 보았다.

나는 유저 모델 안에 time 필드들을 추가했었는데, time관련 필드들은 다른 모델들에서도 계속 사용되어서 아예 모듈화한 듯하다.

참고로 class Meta: abstract=True는 다른 모델들이 이 모델을 상속하기 위해 추가한 것이다.

 

 

 


참고사이트

 

https://velog.io/@lob3767/Django-Timestamp-modelclass-%EC%83%81%EC%86%8D

 

Django Timestamp model(class 상속)

Django에서 데이터 모델을 만들면서 공부하던 중에 겹치는 필드를 계속 작성하는 것에 대한 불편함을 느꼈다. 그래서 class의 상속 기능을 통하여 겹치는 모델의 필드를 모듈화하여 사용해보려 시

velog.io

 

 

https://velog.io/@kimphysicsman/DRF-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%84%A4%EC%A0%95-makepassword#1-%EB%B9%84%EB%B0%80%EB%B2%88%ED%98%B8-%EC%84%A4%EC%A0%95---make_password

 

DRF - 비밀번호 설정 (make_password)

문자열을 암호화 시키는 기능을 가진 Django에서 제공하는 함수 django.contrib.auth.hashers.make_password문자열과 암호화된 비밀번호가 일치하는지 확인하는 함수django.contrib.auth.hashers.check_passwordA

velog.io