목표 : Flask에 회원 비밀번호 암호화 기능을 추가합니다.

 

 

 

1. 암호화 : bcrypt 암호 알고리즘의 특징

일반적인 해시의 취약점을 보완하기 위해 salting과 key stretching 방법이 구현된 bcrypt를 사용합니다.

 - salting : 기존 비밀번호 + 특정문자열 -> 으로 해싱을 진행함

 - key stretching : 단방향 해시 값을 여러차례 계산해내 해시함 (해시 알고리즘의 빠른 실행 속도 덕분에 채택 가능)

 

 

 

2. bcrypt 설치

$ pip install bcrypt

 

 

 

2. 회원가입 부문에 암호화 기능 추가하기

password 정보를 str->bytes로 변경한 후 bcrypt로 암호화하고, 다시 암호화한 데이터를 str로 변형하여 DB에 저장합니다. bytes로 저장시 데이터가 원하는 방향으로 저장되지 않아 str로 저장하였습니다.

# vim app001/models.py

# ...

    def useradd(username, password, email):
        # bcrypt hash transfer
        password = (bcrypt.hashpw(password.encode('UTF-8'), bcrypt.gensalt())).decode('utf-8')
        cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute("INSERT INTO `users` (`username`, `password`, `email`) VALUES (%s, %s, %s)", (username, password, email))
        mysql.connection.commit()
        
# ...

 

 

 

3. 로그인 부문에 암호화 기능 추가하기 ( 매우 중요 )

로그인 시도시에 입력된 password를 str->bytes 로 변경한 데이터와 DB에서 꺼낸 str->bytes 로 변경한 데이터에 대하여 bcrypt.checkpw(A, B) 를 통해 해당 계정의 비밀번호가 일치하는지 확인하고, 정상이면 "check_password=True" & "account=계정정보" 를 return합니다.

 ( 또한, input_password는 bcrypt로 변형되기 전 상태여야하며, account['password'].encode('utf-8')은 bcrypt로 변형된 후의 상태여야 에러없이 checkpw 가능합니다. )

# vim app001/models.py

# ...

class User():
    def login_check(input_username, input_password):
        # bcrypt hash transfer
        input_password = input_password.encode('utf-8')
        # MySQL DB에 해당 계정 정보가 있는지 확인
        cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
        cursor.execute('SELECT * FROM users WHERE username = %s', [input_username])
        # 값이 유무 확인 결과값 account 변수로 넣기
        account = cursor.fetchone()
        check_password = bcrypt.checkpw(input_password, account['password'].encode('utf-8'))
        return account, check_password

# ...

 

 

 

4. models.py의 User.login_check() 함수 return값 2개 가져오도록 수정하기

User.login_check() 함수 return 값을 위에서 2개로 증가시켜주었으니, 받는 변수도 2개로 증가시켜줍니다.

# vim app001/routes.py

# ...

# http://host:5005/login/ - this will be the login page, we need to use both GET and POST requests
@app.route('/login/', methods=['GET', 'POST'])
def login():
    
    # ...
    
        account, check_password = User.login_check(username, password)
    
# ...

 

 

 

5. DB password data & Login/Register 기능 확인

DB에 값도 잘 저장되어있고, 회원가입, 로그인 모두 정상임을 확인합니다.

 

 

 

6. 완성된 코드는 아래에서 다운로드 가능

pyenv_lab.tar.gz
0.12MB

 

 

 

 

+ Recent posts