[TIL] Bcrypt & PyJwt

문성호·2020년 9월 12일
0

Bcrypt & Pyjwt

  • 인증 인가는 한쪽 측면에서 담당하는 것이 아닌 프론트와 백엔드 간의 상호 작용.
  • 인증 구현에 앞서, 개인정보의 보호를 위해 필수적으로 해야 하는 요소인 비밀번호 암호화를 진행. 이 때 암호화 라이브러리인 Bcrypt를 사용한다.
  • 인가할 때는, 입력한 비밀번호와 DB에 저장되어 있는 암호화된 비밀번호를 체킹한 후, 인증 Access Token을 발행하여, 사용자가 Access Token을 가지고 다른 Page를 옮겨 다닐 수 있게 만든다. 이 때 PyJwt(Python에서의 JWT 라이브러리)를 사용한다.

암호화 Flow

1) String -> Byte

  • 사용자에게 입력받는 Password (ex."12345678") 이라고 가정하면, Hashing Algorithm에 입력하기 위해 먼저 Byte형으로 변환해주어야 한다.
    이 과정을 Encoding이라 한다.

     password = '1234'
     encoded_password = bcrypt.encode('utf-8')
      # utf-8 문자 인코딩 방식으로 encode함.

2) Hashing Algorithm으로 Salting + Key Stretching

  hashed_password = bcrypt.hashpw(encoded_password, bcrypt.gensalt())
  • Encoding한 password에 Salt 값을 첨가해서 Hashing Function을 통해 암호화한다.

3) DB에 저장할 땐 다시 String형으로

 saved_password = hashed_password.decode('utf-8')
  • DB에 저장할 땐 String형으로 변환해서 저장한다. 그래서 다시 decoding해준다.

토큰 발행 Flow

if bcrypt.checkpw(hashed_password, saved_password.encode()):
    user_id = {'user-id', 1200} # 실제는 DB에 있는 user의 id를 가지고 온다.
    token = jwt.encode(user_id, 'secret_key', algorithm='HS256')
  • 사용자가 로그인 한 후 다른 웹페이지를 옮겨다닐 때, 다시 로그인 할 필요 없게끔 Ticket을 발행하는 것이 Access Token이라고 한다.

  • 먼저, 사용자가 입력한 PW와 DB에 저장되어 있는 PW를 비교한다.

  • 그러나, 여기서 주의할 점은 토큰을 발행할 때는 DB에 String형으로 저장된 Token을 다시 Byte형으로 변환해서 비교해야 한다.

  • 비교하여 True이면 해당 User를 구분할 수 있는 식별자(대표적으로 id값)과 SECRET_KEY 값, Hashing Algorithm(jwt에서는 HS256이란 알고리즘을 제공한다)을 Argument로 넘겨서 jwt.encode 함수에 넘기면 token을 발행한다.

회원가입 & 로그인 코드에서의 실습

1. 회원가입 View에서 password를 암호화하여 DB에 저장.

 user_data = User(
    phoneNumber = data['phoneNumber'],
    name        = data['name'],
    email       = data['email'],
    password    = bcrypt.hashpw(data['password'].encode('utf-8'), bcrypt.gensalt()).decode('utf-8'),
    ).save()

2. 로그인 View에서 입력받은 password를 DB와 비교 -> Token 발행하는 코드

    savedData = User.objects.get(email=payload['email'])
    if not (savedData and bcrypt.checkpw(payload['password'].encode(), savedData.password.encode())):
      return JsonResponse({'message' : 'INVALID_USER'}, status=401)

    login_token = jwt.encode({'user_id' : savedData.id} , 'secret_key', algorithm = 'HS256').decode() ## string형태의 hashed_pw가 token화 되어서 byte화 되어 나옴.
    return JsonResponse({'access_token':login_token}, status=200)
profile
오늘을 모아 내일을

0개의 댓글