Django Assignment 1 | Westagram 4)

김기현·2022년 2월 22일
0
post-thumbnail

[Mission 5] 회원가입 비밀번호 암호화 적용

미션

  • 암호화 적용
    인증&인가 세션 시간에 배운 내용을 토대로 Mission3의 회원가입 코드에 비밀번호 암호화를 추가합니다.

  • Database 확인
    비밀번호 암호화 후 회원가입을 진행하여 database에 암호화 된 password가 저장 되는지 확인합니다.

수정 사항들 내용

  • 회원가입 코드에 비밀번호 암호화를 추가
  • database에 암호화 된 비밀번호 저장 확인

코드초안

1. 수정하기 전 users/views

import json, bcrypt

from django.http  import JsonResponse
from django.views import View

from users.models import User
from users.validators import validate_email, validate_password

class SignUpView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)

            email        = data['email']
            password     = data['password']
            phone_number = data['phone_number']
            secret_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
            hassed_password = secret_password.decode('utf-8')

            if not validate_email(email):
                return JsonResponse({'Message' : 'Invalid Email'}, status = 400)
            
            if not validate_password(password):
                return JsonResponse({'Message' : 'Invalid Password'}, status = 400)
            
            if User.objects.filter(email = email).exists():
                return JsonResponse({'Message' : 'Email Already Exists'}, status = 400)

            User.objects.create(
                first_name   = data["first_name"],
                last_name    = data["last_name"],
                email        = email,
                password     = secret_password,
                phone_number = phone_number,
                
            )
            return JsonResponse({"MESSAGE": "User Created!"}, status=201)

        except KeyError:
            return JsonResponse({"MESSAGE": "KEY_ERROR"}, status=400)

secret_password를 변수로 두어 해싱과정을 진행하였습니다. 그리고 hashed_password변수에 hash의 기능을 하도록 하였습니다. => 과정을 하나로 붙여 간단하게 풀어나갑니다.

추가적인 기획)
phone_number 전화번호를 사용하지 않아도 되는, 즉 사용자가 전화번호를 회원 가입시 안 넣어도 되는 기획으로 한 번 모델링과 해당 뷰를 수정해보세요!~ abc['def']의 형식은 무조건 키에러를 내는 매핑 방법입니다. 무조건 키에러를 안내도 되는 파이썬 내의 메소드를 찾아서 적용해보세요!~

2. 수정하기 전 users/models

.
.
class User(models.Model):
    first_name   = models.CharField(max_length=50)
    last_name    = models.CharField(max_length=50, null=True)
    email        = models.EmailField(max_length=50, unique=True)
    password     = models.CharField(max_length=100)
    phone_number = models.CharField(max_length=20, blank=True)
    created_at   = models.DateTimeField(auto_now_add=True, null=True)
    updated_at   = models.DateTimeField(auto_now=True, null=True)

    class Meta:
        db_table = "users"

멘토 피드백

수정하기 전 users/views

  • 피드백) Fixed typo(secret_password, hassed)
  • 피드백) 의미론적으로 올바르게 변수를 선언
  • 피드백) decode 추가
  • 피드백) phone_number에 파이썬 메소드 get 사용
  • 추가기획 피드백) checked compatibility between method 'get' and modeling (blank = True, get(a, ''))

코드 개선안

1. 수정 후 users/views

import json, bcrypt

from django.http  import JsonResponse
from django.views import View

from users.models import User
from users.validators import validate_email, validate_password

class SignUpView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)

            email        = data['email']
            password     = data['password']
            phone_number = data.get('phone_number', '')
            hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()).decode('utf-8')

            if not validate_email(email):
                return JsonResponse({'Message' : 'Invalid Email'}, status = 400)
            
            if not validate_password(password):
                return JsonResponse({'Message' : 'Invalid Password'}, status = 400)
            
            if User.objects.filter(email = email).exists():
                return JsonResponse({'Message' : 'Email Already Exists'}, status = 400)

            User.objects.create(
                first_name   = data["first_name"],
                last_name    = data["last_name"],
                email        = email,
                password     = hashed_password,
                phone_number = phone_number,
                
            )
            return JsonResponse({"MESSAGE": "User Created!"}, status=201)

        except KeyError:
            return JsonResponse({"MESSAGE": "KEY_ERROR"}, status=400)

추가적인 기획 개발)

  • 뷰 수정
    "phone_number 전화번호를 사용하지 않아도 되는, 즉 사용자가 전화번호를 회원 가입시 안 넣어도 되는 기획으로 한 번 모델링과 해당 뷰를 수정해보세요!"라는 기획에 phone_number의 속성값을 변경하였습니다.

만약 모델링에서 phone_number의 속성이 null=True(지양해야합니다!)라면 phone_number = data.get('phone_number', None)가 잘 작동하겠지만 기획의 의도와는 다릅니다. 의도대로라면 프론트에서 회원가입 시 입력값을 전혀 받지 않았을 때 phone_number=''라는 속성을 직접 넣어주지 않아도 pass하도록 되어야 합니다. 따라서 phone_number = data.get('phone_number', '')의 속성을 데이터 입력 시 값을 받아올 때 설정해줍니다.

아래의 사진과 같이 의도는 1번 예시처럼 말고, 2번 예시처럼 하도록 합니다.

1번 예시

2번 예시

2. 수정 후 users/models

from django.db import models

class User(models.Model):
    first_name   = models.CharField(max_length=50)
    last_name    = models.CharField(max_length=50)
    email        = models.EmailField(max_length=50, unique=True)
    password     = models.CharField(max_length=100)
    phone_number = models.CharField(max_length=20, blank=True)
    created_at   = models.DateTimeField(auto_now_add=True)
    updated_at   = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = "users"

추가적인 기획 개발)

  • 모델 수정
    "phone_number 전화번호를 사용하지 않아도 되는, 즉 사용자가 전화번호를 회원 가입시 안 넣어도 되는 기획으로 한 번 모델링과 해당 뷰를 수정해보세요!"라는 기획에 user.model안에 있는 phone_number 테이블에 blank=True라는 속성을 넣어주었습니다.
    (참고로 CharField와 TextField에는 null=True라는 속성을 넣는 것을 지양합니다.)
profile
피자, 코드, 커피를 사랑하는 피코커

0개의 댓글