거의 모든 사이트에는 회원가입과 로그인이 필요한데요...!
우아한 꾸까 커머스의 회원가입 페이지입니다.
이메일로 회원가입을 할 때 나타나는 화면은 다음과 같습니다~
westagram에서의 회원가입 미션처럼 차근히 진행합니다..!
from django.urls import path, include
urlpatterns = [
path("users", include('users.urls')),
]
from django.urls import path
from users.views import SignUpView
urlpatterns = [
path("/signup", SignUpView.as_view()),
]
여기서 URI의 마지막 문자로 /
를 사용하지 않아야 합니다. /
는 자원의 계층관계를 나타낼 때 사용되는데, URI의 마지막 문자로 /
를 사용하면 quyery 파라미터나 path 파라미터를 사용하는데 제한이 걸립니다.
import re
def validate_email(email):
email_regex = r'^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
return re.match(email_regex, email)
def validate_password(password):
password_regex = r'^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$'
return re.match(password_regex, password)
정규식을 통해 email과 password가 validate한지 파악합니다.
^
과 $
로 각각 시작과 끝임을 지정하고 원하는 정규식을 입력합니다.
다음의 사이트를 참고하였습니다.
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)
name = data["name"],
email = data['email']
password = data['password']
phone_number = data['phone_number']
birthdate = data["birthdate"]
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(
name = name,
email = email,
password = hashed_password,
phone_number = phone_number,
birthdate = birthdate
)
return JsonResponse({"message": "User Created!"}, status=201)
except KeyError:
return JsonResponse({"message": "KEY_ERROR"}, status=400)
bcrypt라는 라이브러리를 import하여 비밀번호를 encoding하고 랜덤의 값을 salting하여 유추하지 못하게 hashing합니다.
json을 response할 때 보통 Message
보다는 message
처럼 소문자 구성을 많이 사용함을 새로 알았습니다.
from django.urls import path
from users.views import SignUpView, SignInView
urlpatterns = [
path("/signup", SignUpView.as_view()),
path("/signin", SignInView.as_view()),
]
import jwt
from django.http import JsonResponse
from .models import User
from config.settings import SECRET_KEY, ALGORITHM
def login_decorator(func):
def wrapper(self, request, *args, **kwargs):
try:
if 'Authorization' not in request.headers:
return JsonResponse({"message" : "NO AUTHORIZATION IN HEADER"}, status = 401)
access_token = request.headers.get('Authorization')
payload = jwt.decode(access_token, SECRET_KEY, ALGORITHM)
user_id = payload['user_id']
if not User.objects.filter(id = user_id).exists():
return JsonResponse({"message" : "INVALID_UESR"}, status = 401)
request.user = User.objects.get(id = user_id)
return func(self, request, *args, **kwargs)
except jwt.exceptions.DecodeError:
return JsonResponse({"message" : "INVALID_TOKEN"}, status = 400)
except KeyError:
return JsonResponse({"message" : "KEY_ERROR"}, status = 400)
return wrapper
class SignInView(View):
def post(self, request):
try:
data = json.loads(request.body)
signin_email = data['email']
signin_password = data['password']
if not User.objects.filter(email = signin_email).exists():
return JsonResponse({"message" : "INVALID_UESR"}, status = 401)
user = User.objects.get(email = signin_email)
access_token = jwt.encode({'user_id' : user.id}, SECRET_KEY, ALGORITHM)
if not bcrypt.checkpw(signin_password.encode('utf-8'), user.password.encode('utf-8')):
return JsonResponse({"message" : "INVALID_UESR"}, status = 401)
return JsonResponse({"message" : "SUCCESS", "access_token" : access_token}, status = 200)
except KeyError:
return JsonResponse({"message" : "KEY_ERROR"}, status = 400)