유저의 비밀번호를 암호화 하기 위해 사용하는 기술은 일반적으로 단방향 해쉬 함수(one-way hash function)이다. 여기에 기존 단방향 해쉬 함수의 취약점을 보완하기 위해 Salting과 Key Streching 기법이 들어간다.
Salting
: 실제 비밀번호에 더해지는 추가적인 랜덤 데이터. 해쉬 값을 무작위로 만들어준다.
Key Stretching
: 단방향 해쉬값을 계산 한 후 그 해쉬값을 계속 반복해 hashing 하는 것을 의미한다.
Salting과 Key Stretching을 구현한 해쉬 함수중 가장 보편적으로 사용되는 것이 bcrypt
이다. bcrypt는 처음부터 비밀번호를 단방향 암호화 하기 위해 만들어진 해쉬함수이다.
1. 설치
$ pip install bcrypt
Collecting bcrypt
Using cached bcrypt-3.1.7-cp34-abi3-manylinux1_x86_64.whl (56 kB)
Collecting six>=1.4.1
Using cached six-1.14.0-py2.py3-none-any.whl (10 kB)
Collecting cffi>=1.1
Using cached cffi-1.14.0-cp38-cp38-manylinux1_x86_64.whl (409 kB)
Collecting pycparser
Using cached pycparser-2.20-py2.py3-none-any.whl (112 kB)
Installing collected packages: six, pycparser, cffi, bcrypt
Successfully installed bcrypt-3.1.7 cffi-1.14.0 pycparser-2.20 six-1.14.0
2. bcrypt를 통한 암호화
import bcrypt
password = '1234'
bytes(password,'utf-8') # 방법 1
password = password.encode('utf-8')# 방법 2
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
print(hashed_password)
# 출력 : b'$2b$12$z7dSHnEpqUovbFqUB1OeXesMiKaV5O/CtgFnfRhaWX3Wh6bbXRh6O'
hashed_password = hashed_password.decode('utf-8')
print(hashed_password)
# 출력 : $2b$12$GhvfLU5XFhhedwygHmwI.eULRrHkFG8Di.n6IQxs16pTidZ0yFuVW
2. 암호화된 DB와 유저가 입력한 비밀번호를 암호화 한 후 비교하기
user_password = '1234'
user_password = user_password.encode('utf-8')
result = bcrypt.checkpw(user_password,hashed_password)
print(result) # 출력 : True
JWT는 access token을 생성하는 가장 널리 사용되는 기술이다. 말 그대로 사용자의 정보를 담은 JSON 데이터를 암호화해서 클라이언트와 서버간에 주고 받는 것 이다
1. PyJWT 설치
$ pip install PyJWT
Collecting PyJWT
Using cached PyJWT-1.7.1-py2.py3-none-any.whl (18 kB)
Installing collected packages: PyJWT
Successfully installed PyJWT-1.7.1
2.PyJWT를 통한 access token 발급
1. import jwt : 패키지명은 pyjwt이지만 import할때 이름은 jwt이다
import jwt
SECRET = 'secred-key'
payload = {'user_id' : 1}
access_token = jwt.encode(payload,SECRET,algorithm='HS256'
access_token = access_token.decode('utf-8')
print(access_token)
# 출력 : eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxfQ.QjEN7esJq0M_X9TuSjMePV-_nvaI58z6nX5lew2rX0c
3.넘겨받은 access_token 검증하기
access_token = access_token.encode('utf-8') # bytes로 encoding
header = jwt.decode(access_token,SECRET,algorithm = 'HS256')
print(header) # 출력 : {'user_id': 1}
사용자의 정보가 담긴 payload가 출력되었다. payload로 기존 DB와 대조해 사용자가 존재하는지 확인하고 사용자의 권한을 확인한다.
인가는 자주 사용하기 때문에 utils.py(권장), apps.py에 decorator로 따로 구현해준다