위스타그램 3 암호화, 토큰
27 Jul 2021 | 입문 위코드 TIL[Mission 5] 회원가입 비밀번호 암호화 적용
- 유저가 가입할 때 비밀번호를 암호화에서 DB에 저장
Salting(실제 비밀번호 이외에 추가적으로 랜덤 데이터를 더해서 해시값을 계산하는 방법)과 Key Stretching(단방향 해쉬값을 계산 한 후 그 해쉬값을 또 해쉬 하고, 또 이를 반복하는 것을 말한다)을 이용하여 비밀번호를 단방향 암호화하기 위해 만들어진 해쉬함수 bcrypt를 사용한다.
bcrypt 라이브러리 사용하여 비밀번호 암호화
pip install bcrypt
import bcrypt
password = '1234'
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
print(hashed_password)
b'$2b$12$YFs9rh.1LgJwZuf9ibyjpuLvBoCaGX0MzedFWF2Jo0zU3lMZurZ4a'
#yooyoung > users > views.py
import json, re, bcrypt, jwt #brcypt(암호화)와 jwt(토큰) 임포트
#...
from westagram.settings import SECRET_KEY #세팅파일에서 시크릿 키 불러오기
class SignUp(View):
def post(self, request):
try:
data = json.loads(request.body)
hashed_password = bcrypt.hashpw(data['password'].encode('UTF-8'), bcrypt.gensalt())
#유저에게 받은 새 문자열 비밀번호를 인코딩해서 바이트형태로 이진화하고, 비크립트로 암호화한다.
#...
User.objects.create(
password = hashed_password.decode('UTF-8'),
#DB에 문자열로 저장하기 위해서 암호화된 바이트형태의 비밀번호를 디코딩해준다.
)
[Mission 6] 로그인 JWT 적용
- 유저가 입력한 비밀번호 암호화 한후 암호화되서 DB에 저정된 유저 비밀번호와 비교
- 로그인 성공하면 token을 클라이언트에게 전송 (유저는 로그인 성공후 다음부터는 access token을 첨부해서 request를 서버에 전송함으로서 매번 로그인 해도 되지 않도록 한다)
단방향 해쉬 함수(one-way hash function)는 원본 메시지를 알면 암호화된 메시지를 구하기는 쉽지만 암호화된 메시지로는 원본 메시지를 구할 수 없다. 그래서 비밀번호 확인은 bcrypt.checkpw(입력받은 패스워드, 저장된 암호화된 패스워드)매쏘드를 통해서 한다.
password = '1234'
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
new_password = '1234'
bcrypt.checkpw(new_password.encode('utf-8'),hashed_password)
True
class SignIn(View):
def post(self, request):
try:
#...
user = User.objects.get(email=data['email'])
#유저가 반복해서 나오니까 변수로 저장
if not bcrypt.checkpw(data['password'].encode('UTF-8'), user.password.encode('UTF-8')):
return JsonResponse({"massage": "INVALID_USER"}, status=401)
#유저에게 로그인시 입력받은 문자열 비밀번호를 인코딩(이진화)해서 디비에 저장된 비밀번호를 인코딩한 것과 비교해서
#같으면 트루를 반환한다. 같지 않으면 에러를 반환한다.
token = jwt.encode({'user_id': user.id}, SECRET_KEY, algorithm='HS256')
#입력받은 유저의 아이디로 토큰을 생성
return JsonResponse({'token': token}, status = 200)
#이메일과 비밀번호가 일치하는 경우 유저에게 토큰을 전달한다.
except KeyError:
return JsonResponse({"massage": "KEY_ERROR"}, status=400)
JSON Web Token JWT
pip install pyjwt
import jwt
SECRET = 'secret' #'랜덤한 조합의 키' 예제이므로 단순하게 'secret'이라고 하겠습니다.
token = jwt.encode({'id' : 1}, SECRET, algorithm = 'HS256') #토큰을 만드는 문법
print(token)
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MX0.-xXA0iKB4mVNvWLYFtt2xNiYkFpObF54J9lj2RwduAI'
인증(로그인)을 통과한 사용자에게 토큰을 발급한다.
인증을 통과한 사용자만 접근하려면 이 토큰을 받아서 다시 우리가 발행한 토큰이 맞는지 확인한다.
header = jwt.decode(token, SECRET, algorithm = 'HS256')
print(header)
{'id': 1}
인증하는 코드는 보통 user app에 utils.py를 만들어서 데코레이터로 구현한다.
암호화를 하면 이렇게 비밀번호가 암호화된 테이블을 볼 수 있다.