[Django] Westagram 비밀번호 암호화 및token 발행 (bcrypt, jwt)

haejun-kim·2020년 8월 15일
1

[Django]

목록 보기
16/20
post-thumbnail

이 페이지는 위의 개념들을 실제로 코드에 어떻게 적용시킨가에 대한 포스팅입니다.

암호화를 해야하는 이유, bcryp란 무엇인가, JWT란 무엇인가에 대한 개념적인 설명은 아래의 포스팅을 참고

인증 / 인가


westagram에서 회원가입, 로그인, 포스팅, 댓글 관련 엔드포인트를 구현했다. 처음에 내가 구현한 엔드포인트에서는 비밀번호가 암호화가 되어있지 않아 사용자가 입력한 비밀번호가 그대로 노출되었다. 이 문제점을 해결하기 위해 bcrypt와 JWT를 사용했다.

회원가입

signup_user.password = signup_user.password.encode('utf-8')
signup_user.password = bcrypt.hashpw(signup_user.password, bcrypt.gensalt())
signup_user.password = signup_user.password.decode('utf-8')
  • 사용자가 입력한 패스워드는 문자열 타입이기 때문에 해시함수를 사용할 수 없다. 그렇기 때문에 utf-8 형식을 사용하여 문자열을 바이트타입으로 encoding해준다.
  • 파이썬에선 bcrypt 라이브러리를 제공하기 때문에 간단히 설치한 후 import해서 사용할 수 있다. 설치를 완료 한 후 bcrypthashpw 메소드를 사용하여 위에서 endcoding 한 패스워드를 salting 해준다.
  • 현재 해시함수를 거쳐서 암호화 된 패스워드는 바이트 타입이기 때문에 데이터베이스에 바로 저장할 수 없다. 따라서 바이트 타입을 문자열 타입으로 다시 decode해준 후 데이터베이스에 저장한다.

로그인

input_password = data['password']
if bcrypt.checkpw(input_password.encode('utf-8'), signin_user.password.encode('utf-8')):
    token = jwt.encode({'user_id' : signin_user.id}, SECRET_KEY, algorithm = 'HS256')
    # token = jwt.decode(token, SECRET_KEY, algorithm = 'HS256')
    token = token.decode('utf-8')
    return JsonResponse({'token' : token}, status = 200)
  • 사용자가 입력한 패스워드를 새로운 변수에 할당시켜주고, bcrypt 라이브러리에서 제공해주는 checkpw 메소드를 사용하면 데이터베이스에 저장되어 있는 해당 사용자의 암호화 된 비밀번호와 현재 사용자가 입력 한 비밀번호를 비교할 수 있다. 이 때, 주의할 점은 데이터베이스에는 디코딩해서 문자열 상태로 저장했기 때문에 이를 직접적으로는 비교할 수가 없기 때문에 다시 바이트 타입으로 인코딩해주어야한다.
  • jwt 라이브러리를 통해서 SECRET_KEY와 어떤 알고리즘을 사용하여 토큰을 발행할 것인지에 대한 정의를 내려준다.
  • 비교가 완료 됐으면 다시 문자열로 디코딩해주어야 하는데 이 때 두가지 선택지가 있다.
    1. jwt 라이브러리에서 제공해주는 디코딩 : jwt는 header, payload, signature로 구성되어 있는데 jwt.decode()를 사용하면 payload의 내용만 디코딩해준다. signature에는 private한 정보들이 들어있기 때문에 웬만하면 이 메소드를 사용하도록 하자.
    2. 내장함수에서 제공해주는 디코딩 : jwt.decode()와는 다르게 header, payload, signature 모두 디코딩해준다.
  • 디코딩 했으면 그 결과값을 다시 보내줘야한다. JsonResponse를 통해 딕셔너리 형태로 토큰값을 보내주면 토큰값을 발행이 완료 된 것을 확인할 수 있다.

실행 결과

암호화 되어 비밀번호 저장

토큰 발행

0개의 댓글