장고로 회원가입과 로그인 기능을 구현한 후
패스워드 암호화 기능을 구현하였다.
우선 패스워드를 도대체 왜
암호화해야하는 것인지 먼저 알아야한다.
패스워드를 평문으로 저장하면 왜 안되는가?
서버의 데이터베이스가 털렸을 때도 회원의 패스워드를 알 수 없게 만들기 위한 것이다.
패스워드가 잘 해싱되어 있으면 해커가 그 해시 값을 보더라도 사용자의 계정으로 로그인할 수 없기 때문에 해커에게 의미 없는 정보가 된다.
만약 해싱이되어있지 않고 서버자체를 원천봉쇄한다고 해도 데이터베이스를 다루는 개발자가 데이터베이스에 있는 정보를 볼 수 있으므로
해싱이 가장 안전한 방법이다.
encode_password = bcrypt.hashpw(data['password'].encode('utf-8'),
bcrypt.gensalt())
decode_password = encode_password.decode('utf-8')
우선 bcrypt를 이용하여 유저가 회원가입할 때 입력하는 password자체를 인코딩해준다.
인코딩 = 코드화 = 암호화 = 부호화
인코딩은 어떤 문자를 컴퓨터가 이해할 수 있는 bytes로 바꿔준다고 이해하면 되고
디코딩 = 역코드화 = 복호화
반대로 디코딩은 다시 사람이 알 수 있게 바꿔주는 것을 말한다.
해싱한 암호를 다시 디코딩 해서 DB에 저장 가능한 형태로 만들어준다
User.objects.create( name = data['name'], email = data['email'], password = decode_password, phone_number = data['phone_number'], information = data['information'], )
그럼 마찬가지로 password 입력 부분도 바꿔주면 된다.
class LoginView(View):
def post(self,request):
data = json.loads(request.body)
try :
if not User.objects.filter(email=data['email']).exists():
return JsonResponse({"message": "INVALID_USER"}, status=401)
users = User.objects.get(email=data['email'])
if bcrypt.checkpw(data['password'].encode('utf-8'), users.password.encode('utf-8')) == True:
access_token = jwt.encode({'id':users.id}, SECRET_KEY, algorithm=ALGORITHM)
return JsonResponse({'token': access_token}, status=200)
return JsonResponse({"message": "INVALID_USER"}, status=401)
except :
return JsonResponse({"message": "KEY_ERROR"}, status=400)
코드를 살펴보면 유저가 입력한 패스워드를 인코딩하고
데이터베이스에 있던 기존의 패스워드를 인코딩 한 후에
비교해서 맞으면 토큰값을 보내준다.
꼭 토큰에 들어가는 시크릿키와 알고리즘은 gitignore되있는 파일에 저장해야한다.
salt값은 계속 바뀌는데 어떻게 다른 시기에 입력한 두 값이 같은 줄 알 수 있을까?
멘토님에게 물어보니 salt값은 어디 따로 저장돼있는 개념이 아닌 값을 비교할 상황마다
휘발성으로 다시 복잡한... 알고리즘으로 어디서 기억하여서 비교할수 있는 것이라고 하였다.!