class LoginView(View):
def post(self, request):
try:
data = json.loads(request.body)
email = data['email']
password = data['password']
if not User.objects.filter(email=email).exists():
return JsonResponse({'message':'INVALID_USER'}, status=401)
if not password == User.objects.get(email=email).password:
return JsonResponse({'message':'INVALID_USER'}, status=401)
return JsonResponse({'message':'SUCCESS'}, status=200)
except KeyError:
return JsonResponse({'message':'KEY_ERROR'], status=400)
1
email이 존재하지 않으면 invalid_user, 401 반환
2
password가 일치하지 않으면 invalid_user, 401 반환
3
key error 발생 시 key_error, 400 반환
from django.urls import path
from users.views import LoginView
urlpatterns = [
path('/login', LoginView.as_view()), ]
비밀번호가 노출되지 않도록 암호화하여 저장하는 작업을 추가한다.
import bcrypt
data = json.loads(request.body)
password = data['password']
hash_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
User.objects.create(
name = data['name'],
email = data['email'],
password = hashed_password.decode('utf-8'),
contact = data['contact']
)
주의
- DB에 암호화된 비밀번호(hashed_password)를 저장할 때 decode 한다. (
byte
->str
)
byte
타입일 경우 b' 표식 자체도 스트링으로 인식해서 로그인 기능 구현시 올바른 비교를 할 수 없다.
import jwt
from my_settings import SECRET_KEY
data = json.loads(request.body)
password = data['password']
user = User.objects.get(email=data['email'])
if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')
return JsonResponse({'message':'INVALID_USER'}, status=401)
token = jwt.encode({'id':user.id}, SECRET_KEY, algorithm = 'HS256')
return JsonResponse({'access_token' : token }, status=200)
주의
bcrypt.checkpw()
의 비교대상 : 사용자가 입력한 비밀번호를 encode한 값 - 암호화한 상태의 DB에 기록된 비밀번호를 encode한 값 (str
->byte
)- token에 로그인한 사용자의 id값을 담아서 프론트엔드로 보낸다.
SECRET_KEY
는 보안관련 비공개값이므로 직접 입력하지않고my_settings
파일에서 import한다.