오늘도 개발

[Westagram] 잘못된 로그인 시도 시 발생하는 에러 본문

TIL & 프로젝트 회고

[Westagram] 잘못된 로그인 시도 시 발생하는 에러

Sueeeeeee 2022. 7. 8. 16:51

Westagram은 이메일과 비밀번호로 로그인할 수 있는 앱이다.

Westagram에 정상적으로 로그인 하려면 다음과 같은 조건을 만족해야 한다.

 

- 요청 메시지에 email, password 키가 존재한다.

- DB에 존재하는 email이다.

- DB에서 email과 비밀번호가 일치한다.

 

우선 올바른 형식의 요청 메시지를 받아 로그인에 성공하는 경우를 살펴보자. 

알맞은 요청 메시지 예시는 다음과 같다.

http -v POST 127.0.0.1:8000/users/login email='younghee@naver.com' password='123abc!!'

이 요청 메시지는 다음 LoginView 함수를 거쳐,

class LoginView(View):
    def post(self, request):
        # 1. 키가 있는지 확인
        try:
            request_data = json.loads(request.body)
            email        = request_data['email']
            password     = request_data['password']
        except KeyError:
            return JsonResponse({'message' : 'KEY_ERROR'}, status = 400)

        try:
            # 2. 가입된 이메일인지 확인
            # 3. 이메일과 비번이 일치하는지 확인
            if not User.objects.get(email=email).password == password:
                return JsonResponse({'message' : 'INVALID_USER'}, status = 401)
        except ObjectDoesNotExist:
            return JsonResponse({'message' : 'INVALID_USER'}, status = 401)

        return JsonResponse({'message' : 'SUCCESS'}, status = 200)

다음과 같은 응답을 반환한다.

HTTP/1.1 200 OK
Content-Length: 22
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sat, 09 Jul 2022 04:36:36 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.9
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "message": "SUCCESS"
}

이제 로그인을 실패시켜야 하는 경우를 살펴보자. 

 

1. 요청 메시지 형식이 틀린 경우

요청 메시지가 잘못된 경우 에러를 발생시켜야 한다.

예를 들어 다음과 같은 경우, email이라는 항목이 빠져있다. 

email 정보가 없으면 로그인이 불가능하기 때문에 오류를 발생시켜야 한다.

http -v POST 127.0.0.1:8000/users/login password='123abc!!'

이 메시지를 장고에서 json으로 변환하면 다음과 같은 딕셔너리가 된다.

{'password': '1234!a'}

이 딕셔너리에서 'email' 항목을 사용하려고 하면 키가 없기 때문에 파이썬이 KeyError를 발생시킨다.

try, except문으로 KeyError가 나오면 400 에러 메시지를 응답하도록 만들었다.

# 1. 키가 있는지 확인
try:
    request_data = json.loads(request.body)
    email        = request_data['email']
    password     = request_data['password']
except KeyError:
    return JsonResponse({'message' : 'KEY_ERROR'}, status = 400)

위의 요청은 다음과 같은 응답을 받게 된다. 

HTTP/1.1 400 Bad Request
Content-Length: 24
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sat, 09 Jul 2022 04:41:15 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.9
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "message": "KEY_ERROR"
}

 

2. 가입된 이메일이 아닌 경우 / 이메일과 비밀번호가 일치하지 않는 경우

요청 메시지가 알맞은 형식으로 잘 온 경우, 메시지의 내용을 확인해야 한다.

요청 메시지의 이메일이 DB에 없는 경우, 가입된 유저가 아니라는 뜻이므로 오류를 발생시켜야 한다.

이메일이 DB에 있지만 비밀번호가 요청 메시지의 비밀번호와 일치하지 않는 경우, 잘못된 유저라는 뜻이므로 오류를 발생시켜야 한다.

 

이 두 경우는 다음과 같은 코드로 구현할 수 있다.

try: 
    if not User.objects.get(email=email).password == password:
        return JsonResponse({'message' : 'INVALID_USER'}, status = 401)
except ObjectDoesNotExist:
    return JsonResponse({'message' : 'INVALID_USER'}, status = 401)

우선 User.objects.get(email=email)로 가입된 유저인지 확인한다. 

해당 email이 DB에 없으면 파이썬은 ObjectDoesNotExist 에러를 발생시키므로, 

ObjectDoesNotExist 에러가 발생하는 경우 다음과 같은 응답 메시지를 보내도록 만들었다.

(Status code 401은 클라이언트가 리소스에 접근할 자격이 없다는 뜻이다.) 

HTTP/1.1 401 Unauthorized
Content-Length: 27
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Sat, 09 Jul 2022 04:46:15 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.9
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "message": "INVALID_USER"
}

User.objects.get(email=email)이 통과했다면 이제 이 유저의 비밀번호와 요청 메시지의 비밀번호가 일치하는지 확인해야 한다.

User.objects.get(email=email).password == password로 확인해보고, 

True가 아닌 경우 위와 동일한 응답 메시지를 전송한다.