Instagram clone - 회원가입 및 로그인 (bcrypt, jwt)

Joey Lee·2020년 5월 19일
0

Django

목록 보기
8/23

필요한 모듈이 설치되어 있지 않다면 설치합니다.

> pip install bcrypt
> pip install pyjwt

1. 회원가입 API

User App의 Views.py 파일에 회원가입을 위한 SignUpView를 아래와 같이 작성합니다.

1) 구성 로직

  • request 요청을 data 변수에 담기

  • 패스워드를 bcrypt로 암호화하여 hashed_password로 담기

    (str인 자료형을 encode하여 bytes로 형변환함)

  • request 전송된 name, emailhashed_password를 객체를 생성하고 저장
    (bytes을 decode하여 str으로 형변환해 DB에 저장)

  • 200 OK 메시지 JSON으로 리턴
    (이하 예외 처리는 생략함)

2) 전체 코드

class SignUpView(View):
  def post(self, request):
    data = json.loads(request.body)
        
    # name, email, password 미입력시 처리 + name/email 이미 존재할 때 처리
    try:  
      hashed_password= bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt())
                
      User(
           name = data['name'],            
           email = data['email'],
           password = hashed_password.decode('utf-8')
      ).save()
      return JsonResponse({'message':'SUCCESS'}, status=200)
# 이하 예외 처리는 생략함

3) 실행 결과 (httpie)

❯ http -v http://127.0.0.1:8000/user/ name=young email=young@young.com password=1234
POST /user/ HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 65
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.1.0

{
    "email": "young@young.com",
    "name": "young",
    "password": "1234"
}

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Date: Wed, 20 May 2020 03:00:49 GMT
Server: WSGIServer/0.2 CPython/3.7.7
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "message": "SUCCESS"
}

2. 로그인

User App의 Views.py 파일에 로그인을 위한 LoginView를 아래와 같이 작성합니다.

1) 로그인 API 구성 로직

  • request 요청을 data 변수에 담기

  • name(사용자ID), password 미입력 시 400 JSON 리턴

  • data['name']과 동일한 name을 가진 객체가 존재할 경우 아래 구문 실행

  • data['password']user.passwordbcypt.checkpw 메소드로 확인 -> True일 경우 아래 구문 실행
    (2개 데이터는 encode하여 bytes로 형변환한 뒤 비교)

  • jwt로 access_token을 만들어 token 변수에 담기

  • token 변수를 {'token' : token.decode('utf-8')} JSON에 담아서 전달

2) 로그인 API 전체 코드

class LoginView(View):
  def post(self, request):
    data = json.loads(request.body)
    checked_name = data.get('name', None)   
    # 데이터 안 넘어올 때 에러 방지 위해 없애려 None 처리
    checked_password = data.get('password', None)

    # name, pass 미입력, name 존재하지 않을 시 처리 후 진행
    try:         
      if checked_name == '':
         return JsonResponse({"message" : "Please enter ID"}, status=400)
      elif checked_password == '':
         return JsonResponse({"message" : "Please enter password"}, status=400)

      elif User.objects.filter(name=checked_name).exists():
          user = User.objects.get(name=checked_name)                
          if bcrypt.checkpw(checked_password.encode('utf-8'), user.password.encode('utf-8')):
             token = jwt.encode({'user_id': user.id}, 'secret', algorithm='HS256')
             return JsonResponse({'token' : token.decode('utf-8')}, status=200)
          return JsonResponse({"message" : "INVALID_PASSWORD"}, status=400)
# 이하 예외 처리는 생략

3) 실행 결과 (httpie)

❯ http -v http://127.0.0.1:8000/user/login/ name=young password=1234
POST /user/login/ HTTP/1.1
Accept: application/json, */*;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Content-Length: 37
Content-Type: application/json
Host: 127.0.0.1:8000
User-Agent: HTTPie/2.1.0

{
    "name": "young",
    "password": "1234"
}

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Date: Wed, 20 May 2020 07:44:09 GMT
Server: WSGIServer/0.2 CPython/3.7.7
Vary: Origin
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

{
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxMX0.8WeBhffU-wMdOhE4zdS3KJx2XfCYVpAoPNwSjaRovn4"
}
profile
안녕하세요!

0개의 댓글