1
0
mirror of https://github.com/avatao-content/test-tutorial-framework synced 2024-11-14 21:37:17 +00:00

Use best practices for password hashing in webservice

This commit is contained in:
Kristóf Tóth 2018-04-28 16:13:35 +02:00
parent db9e2c055f
commit bb4745ed47
3 changed files with 18 additions and 12 deletions

View File

@ -2,7 +2,8 @@ FROM eu.gcr.io/avatao-challengestore/tutorial-framework
# Install webservice dependencies # Install webservice dependencies
RUN pip3 install Flask==1.0 \ RUN pip3 install Flask==1.0 \
SQLAlchemy==1.2.7 SQLAlchemy==1.2.7 \
passlib==1.7.1
# Define variables to use later # Define variables to use later
ENV TFW_SERVER_DIR="/srv/.tfw" \ ENV TFW_SERVER_DIR="/srv/.tfw" \

View File

@ -1,6 +1,7 @@
from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.orm import scoped_session, sessionmaker
from passlib.hash import pbkdf2_sha256
engine = create_engine('sqlite:///db.db', convert_unicode=True) engine = create_engine('sqlite:///db.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False, db_session = scoped_session(sessionmaker(autocommit=False,
@ -20,3 +21,13 @@ class User(Base):
def init_db(): def init_db():
Base.metadata.create_all(bind=engine) Base.metadata.create_all(bind=engine)
class PasswordHasher:
@staticmethod
def hash(password):
return pbkdf2_sha256.hash(password)
@staticmethod
def verify(password, hash):
return pbkdf2_sha256.verify(password, hash)

View File

@ -1,9 +1,8 @@
from os import urandom, getenv from os import urandom, getenv
from hashlib import sha512
from flask import Flask, render_template, request, session, url_for from flask import Flask, render_template, request, session, url_for
from model import db_session, init_db, User from model import db_session, init_db, User, PasswordHasher
BASEURL = getenv('BASEURL', '') BASEURL = getenv('BASEURL', '')
init_db() init_db()
@ -21,18 +20,12 @@ def remove_db_session(exception=None):
db_session.remove() db_session.remove()
def hash_password(password):
salt = 'justsomerandombytes'.encode()
return sha512(password.encode()+salt).hexdigest()
@app.route('/', methods=['GET', 'POST']) @app.route('/', methods=['GET', 'POST'])
def index(): def index():
if request.method == 'POST': if request.method == 'POST':
user = User.query.filter(User.username == request.form['username'], user = User.query.filter(User.username == request.form['username']).first()
User.passwordhash == hash_password(request.form['password'])).first()
if not user: if not user or not PasswordHasher.verify(request.form['password'], user.passwordhash):
return render_template('login.html', alert='Invalid credentials!') return render_template('login.html', alert='Invalid credentials!')
else: else:
session['logged_in'] = True session['logged_in'] = True
@ -53,10 +46,11 @@ def register():
return render_template('register.html', alert='Username already in use.') return render_template('register.html', alert='Username already in use.')
db_session().add(User(username=request.form['username'], db_session().add(User(username=request.form['username'],
passwordhash=hash_password(request.form['password']))) passwordhash=PasswordHasher.hash(request.form['password'])))
db_session().commit() db_session().commit()
return render_template('login.html', success='Account "{}" successfully registered. You can log in now!'.format(request.form['username'])) return render_template('login.html', success='Account "{}" successfully registered. You can log in now!'.format(request.form['username']))
return render_template('register.html') return render_template('register.html')