이번 파트야말로 정말 선배 기수 분들의 블로그 정리가 많이 도움이 되었다. 공부할 겸 거의 카피코딩에 가까운 방식을 사용한 점이 제일 아쉽지만, 결과물을 내꺼로 만들어서 1차 프로젝트 때는 혼자 힘으로 해봐야겠다. 인증인가 자체가 어려워서 자주 반복학습이 필요할 것 같다.
(코드)
account/views.py
import json
import bcrypt
import jwt
from django.views import View
from django.http import JsonResponse
from .models import User
from my_settings import SECRET_KEY
해결하기 위한 선행과제
1) bcrypt, jwt를 모두 설치한다(pip install~)
2) import 해온다.
3) JWT로 서버 간 자유롭게 활용하려면 시크릿키가 필요하므로 시크릿키도 불러온다.
class SignupView(View):
def post(self, request):
try:
data = json.loads(request.body)
if User.objects.filter(email=data['email']).exists():
return JsonResponse({"message": "EMAIL_ERROR"}, status=400)
if User.objects.filter(password=data['password']).exists():
return JsonResponse({"message": "PASSOWRD_ERROR"}, status=400)
if '@' in data['email'] and '.' in data['email'] and len(data['password']) >= 8:
byted_password = data['password'].encode('utf-8')
# 해싱 전 입력하는 패스워드 인코딩
hash_password = bcrypt.hashpw(byted_password, bcrypt.gensalt()).decode()
# 사용자가 입력한 값을 해싱하는 과정
# 마지막에 decode 다시 안 해주면 해싱된 값으로만 저장되어서 로그인 불가능(사용자도 서버도 아무도 몰라..)
password = hash_password
user = User.objects.create(
email = data['email'],
password = password
# 위에서 이미 패스워드 해쉬 해버림
)
# 값 세이브 필요 없어서 지움
return JsonResponse({"message": "SUCCESS"}, status=200)
return JsonResponse({"message":"MAKE_FAIL"}, status=400)
except KeyError:
return JsonResponse({"message": "KEY_ERROR"}, status=400)
class LoginView(View):
def post(self, request):
try:
data = json.loads(request.body)
user = User.objects.get(email=data['email'])
# 유저는 이메일 데이터로 가져오고(1:1매칭이므로)
if bcrypt.checkpw(data['password'].encode('utf-8'), user.password.encode('utf-8')):
# 만일 인코딩 된 패스워드와 저장된 패스워드 데이터가 동일하다면
token = jwt.encode({'email' : data['email']}, SECRET_KEY, algorithm="HS256")
# 토큰에 정보 : 유저정보, 시크릿키, 적용하고자 하는 알고리즘 발행
# 클라이언트에게 이메일 부분을 암호화 하여 보내줌.(by json body)
# 클라이언트는 헤더에 토큰을 담아서 보내줘야 함.
# h5yp 버전 문제로 디코드 안 해도 됨.
'''(인가 절차)
1. 인가 절차를 통해 어세스 토큰을 생성(user_id...)
2. 유저가 리퀘스트 보낼 때 어세스 토큰을 보낸다.'''
return JsonResponse({"message":"SUCCESS"}, status=200)
'''(인가 절차)5. user_id 사용해서 데이터베이스 해당 유저 권한을 확인한다.
6. 유저가 권한 있는지 확인 후 요청 처리 / 에러 보낸다.'''
else:
return JsonResponse({"message":"INVALID_USER"}, status=401)
except KeyError:
return JsonResponse({"message":"KEY_ERROR"}, status=400)
class TokenCheckView(View):
def post(self,request):
data = json.loads(request,body)
user_token_info = jwt.decode(data['token'], SECRET_KEY, algorithms='HS256')
# 받아온 유저의 정보는 jwt 라이브러리로 토큰 값을 디코드 하여 원래 유저와 같은지 비교
'''(인가 절차) 3. 서버에서는 유저가 보낸 어세스 토큰을 복호화 한다.
4. 복호화 된 데이터를 통해 user_id를 얻는다.'''
if User.objects.filter(email=user_token_info['email']).exists():
return JsonResponse({"message": "SUCCESS"}, status=200)
# 리턴된 유저 정보가 데이터와 동일하면 성공
# (인가절차)5. user_id 사용해서 데이터베이스 해당 유저 권한을 확인한다.
return JsonResponse({"message":"INVALID_USER"}, status=401)
인가되지 않으면 실패
# (인가 절차) 6. 유저가 권한 있는지 확인 후 요청 처리 / 에러 보낸다.