Mini Project | 암호화 및 인증 토큰 발행하기

Hyeonju L.·2020년 12월 13일
0

Project

목록 보기
4/8

회원가입/로그인 엔드포인트의 마지막 단계 - 인증, 인가 구현

1. bcrypt 암호화

개인정보보호를 위해 필수 요소인 비밀번호 암호화

bcrypt는 string(문자열) 데이터가 아닌 Bytes(이진화) 데이터를 암호화한다.
이용자가 회원가입 시 기입하는 비밀번호는 string이기 때문에 비밀번호를 Bytes로 변환하여 암호화를 해야한다.

  • encode : str > Bytes
  • decode : Bytes > str
  • encode, decode 시에는 'utf-8' 유니코드 문자 규격 이용

  • bcrypt 설치
pip install bcrypt
  • 비밀번호 암호화 실습
import bcrypt		# bcrypt 라이브러리 import

password = '1234'	
type(password)
<class 'str'>		# 입력된 비밀번호 타입: string(문자열)

hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())	# 비밀번호 암호화
type(hashed_password) 
<class 'bytes'>		# 암호화된 비밀번호 타입: bytes

  • 비밀번호 복호화 실습
new_pw = '1234'
bcrypt.checkpw(new_pw.encode('utf-8'), hashed_password)

여기서 new_pw.encode('utf-8')은 사용자가 로그인 시 입력하는 비밀번호고,
hashed_password는 저장되어있는 암호화된 비밀번호이다.

회원가입 및 로그인에 적용

import bcrypt		# bcrypt import

# 회원가입(signup)
class SignupView(View):
	def post(self, request):
    		data = json.loads(request.body)

		email_validation = '^[a-zA-Z0-9+-_.]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
        	pw_validation = '^[A-Za-z0-9@#$%^&+=]{8,}$'
            
            	try:         
                	if not re.match(email_validation, data['email']):
  				return JsonResponse(
  					{"message":"INVALID_ID"}, status = 401
					)
                
                	if not re.match(pw_validation, data['password']:
				return JsonResponse(
                                        {"message":"INVALID_PW"}, status = 400
                                        )

                        if Users.objects.filter(email=data['email']).exists():
				return JsonResponse(
					{"message":"USER_EXIST"}, status = 400
					)

		else:	 # 에러 발생시키지 않는 경우 이메일, 암호화된 비밀번호를 다시 string으로 변환해 저장
			Users.objects.create(
				email = data['email'],
				password = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8')
				).save()
 
			return JsonResponse({'message': 'SUCCESS'}, status = 
 
		except KeyError:
			return JsonResponse({"message":"KEY_ERROR"}, status = 400)


# 로그인(signin)
class SigninView(View):
	def post(self, request):
		data = json.loads(request.body)

		try:
			if Users.objects.filter(email=data['email']).exists():
				user = Users.objects.get(email=data['email'])

				# 암호화된 비밀번호 복호화해서 저장되어 있는 비밀번호와 비교, 동일하면 success 반환
				if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):

					return JsonResponse({"message":"SUCCESS"}, status = 200)
			
            			return JsonResponse({"message": "INVALID_PW"}, status = 401)
                        
		else:
			return JsonResponse({"message":"INVALID_USER"}, status = 401)
		
        	except KeyError:
			return JsonResponse({"message":"KEY_ERROR"}, status = 400)

2. JSON Web Token 발행

사용자 인증을 위한 JWT 구현

  • pyjwt 설치
pip install pyjwt		# pyjwt 설치
  • jwt 발행 실습
import jwt			# jwt import

SECRET = 'secret'		# settings.py 에 들어있는 secret key

access_token = jwt.encode({'id':1}, SECRET, algorithm='HS256')
# user(id=1)에 대한 Token 발행

로그인 시 토큰 발행 및 return

import jwt		# jwt import

from my_settings import SECRET	# my_settings에 있는 SECRET key 참조

# 로그인 view
class SigninView(View):
	def post(self, request):
		data = json.loads(request.body)

		try:
			if Users.objects.filter(email=data['email']).exists():
				user = Users.objects.get(email=data['email'])

				if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
					
                    			access_token = jwt.encode({'id'=user.email}, SECRET, algorithm = 'HS256').decode('utf-8')
					
                    			return JsonResponse({"message":"SUCCESS", "Token": access_token}, status = 200)
			
            			return JsonResponse({"message": "INVALID_PW"}, status = 401)
                        
		else:
			return JsonResponse({"message":"INVALID_USER"}, status = 401)
		
        	except KeyError:
			return JsonResponse({"message":"KEY_ERROR"}, status = 400)

비밀번호 암호화, JWT는 개념 이해만 하면 그렇게 어렵지는 않아서 금방 구현을 했다.
암호화, JWT 구현을 처음부터 할 수 있었으면 고려해서 코드를 짰을텐데, 나중에 적용하느라 처음짰던 코드를 계속 변경해야해서 그런 과정에서 고민을 하고 공부가 좀 더 됐던 것 같다.

이렇게해서 암호화와 JWT가 들어간 회원가입 및 로그인 엔드페이지 구현 완료 :)

profile
What you think, you become. What you feel, you attract. What you imagine, you create.

0개의 댓글