Django Assignment 1 | Westagram 5)

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

[Mission 6] 로그인 JWT 발급

미션

  • 로그인 로직 변경
    비밀번호 암호화 로직을 적용했기 때문에 이에 맞게 로직을 변경합니다.
    bcryptcheckpw method을 이용하여 비밀번호 확인 로직을 추가합니다.
    비밀번호가 틀렸을 때 적절한 에러를 반환합니다.

  • JWT 발급
    로그인 성공시 JWT의 payload에 로그인 한 user의 id를 담아서 발급해 주세요.

수정 사항들 내용

  • bcrypt의 checkpw method을 이용하여 비밀번호 확인 로직을 추가 완료
  • 로그인 성공시 JWT의 payload에 로그인 한 user의 id를 담아서 발급 완료
  • 발급한 JWT를 응답의 데이터로 반환
  • pip install pyjwt로 jwt설치 및 import 완료

코드초안

1. 수정하기 전 LoginView

import json, bcrypt, jwt

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

from users.models     import User
from users.validators import validate_email, validate_password
from secret           import ALGORITHM
from config.settings  import SECRET_KEY


class LoginView(View):
    def post(self, request):
        try:
            data     = json.loads(request.body)
            email    = data['email']
            password = data['password']
            user     = User.objects.get(email=email) 

            if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')):
                return JsonResponse({"message" : "WRONG_PASSWORD"}, status = 401)

            access_token = jwt.encode({'id' : user.id}, SECRET_KEY, ALGORITHM)
            return JsonResponse({"message" : "LOGINSUCCESS! JWT: " + access_token}, status = 201)
            
        except KeyError:
            return JsonResponse({"message": "KEY_ERROR"}, status=400)
        
        except User.DoesNotExist:
            return JsonResponse({"message" : "INVALID_EMAIL"}, status = 400)

해당 이메일을 사용하는 유저를 user에 저장하고, 토큰을 발행합니다. 만약 사용자가 입력한 패스워드의 인코딩값이 유저의 비밀번호를 인코딩 한 값이 일치하지 않으면(유저를 생성할 때 비밀번호를 디코딩 해서 str타입으로 넣기 때문), 유저가 비밀번호를 잘못 입력한 것이기 때문에 'Wrong_Password'를 전달합니다.

다음으로 JWT를 발급합니다. 토큰의 변조는 signature 영역에서 해결되는데 signature가 만들어지기 위해서는 인코딩 된 header, 인코딩 된 payload, 그리고 secret이 필요합니다. (Simple JWT에서는 secret으로 Django 프로젝트마다 사용하는 secret_key를 기본으로 이용합니다.)

그 후에 성공의 메시지와 함께 토큰을 발행합니다.

멘토 피드백

  • "message" : "xxx", "token" : token 의 내용이 들어가야 함

코드 개선안

1. 수정 후 LoginView

.
.
.
class LoginView(View):
    def post(self, request):
        try:
            data     = json.loads(request.body)
            email    = data['email']
            password = data['password']
            user     = User.objects.get(email=email) 

            if not bcrypt.checkpw(password.encode('utf-8'), user.password.encode('utf-8')):
                return JsonResponse({"message" : "WRONG_PASSWORD"}, status = 401)

            access_token = jwt.encode({'id' : user.id}, SECRET_KEY, ALGORITHM)
            return JsonResponse({"message" : "LOGIN_SUCCESS!", "token" : access_token}, status = 201)
            
        except KeyError:
            return JsonResponse({"message": "KEY_ERROR"}, status=400)
        
        except User.DoesNotExist:
            return JsonResponse({"message" : "INVALID_EMAIL"}, status = 401)

과제를 하면서 만났던 에러들

  • Error1

SECRET 값을 import할 때 생긴 오류입니다. 뭔가 잘못 입력해서 import 오류가 생겼는데 그 후에 AppRegistryNotReady: Apps aren't loaded yet 에러를 내뱉습니다.... ㅎㅎ(당황) SECRET을 Django 프로젝트마다 사용하는 시크릿키로 바꾸고 적절하게 import를 한 후에 수월히 해결되었습니다.

제대로 먹히지 않을 코드를 작성하는 것 이외에 해당의 오류가 발생했다면 다음의 사이트를 참고하는게 좋을 것 같습니다.

(보통은 위에서 언급했듯 Simple JWT에서는 secret으로 Django 프로젝트마다 사용하는 secret_key를 기본으로 이용합니다! 꼭 그렇게 하세요!)

  • Error2

해당 오류는 user=User.objects.get(email=email)이 위에 있어서 생기는 오류인데 당장은 DB상에서 찾지 못하기 때문입니다. 그러기에 메시지로 원하는 문장을 내뱉지 못하고 서버단에서 에러를 내뱉습니다. 따라서 에러를 해결하기 위해서 user가 필요한 비밀번호 검증 바로 위에 해당 코드를 입력합니다.

profile
피자, 코드, 커피를 사랑하는 피코커

0개의 댓글