개인정보보호를 위해 필수 요소인 비밀번호 암호화
bcrypt는
string(문자열)
데이터가 아닌Bytes(이진화)
데이터를 암호화한다.
이용자가 회원가입 시 기입하는 비밀번호는string
이기 때문에 비밀번호를Bytes
로 변환하여 암호화를 해야한다.
- encode :
str
>Bytes
- decode :
Bytes
>str
- encode, decode 시에는 'utf-8' 유니코드 문자 규격 이용
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)
사용자 인증을 위한 JWT 구현
pip install pyjwt # pyjwt 설치
import jwt # jwt import
SECRET = 'secret' # settings.py 에 들어있는 secret key
access_token = jwt.encode({'id':1}, SECRET, algorithm='HS256')
# user(id=1)에 대한 Token 발행
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가 들어간 회원가입 및 로그인 엔드페이지 구현 완료 :)