-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
HashProperty
Mike Bayer edited this page Feb 13, 2014
·
1 revision
Note: Please see UsageRecipes/DatabaseCrypt for a modernized version of database-side crypt() mapping.
Attached is a small library (with no dependency on SQLAlchemy) to implement hashed storage of passwords. Example usage in SQLAlchemy context below:
#!python
from sqlalchemy import create_engine, Column, Integer, String, func
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from hashed_property import HashedProperty
# Set up a standard declarative base class and an engine
Base = declarative_base(bind=create_engine('mysql://root@localhost/test'))
# A user class
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(String(100), nullable=False)
# These are the columns that will hold the values
password_hash = Column(String(40), nullable=False)
password_salt = Column(String(40), nullable=False)
# This is the proprty that will be used as interface
password = HashedProperty('password_hash', 'password_salt',
# Optional function to enable generating the hash on the db side
dbhashfunc=(lambda pw,salt: func.sha1(pw + salt)))
# For pretty printing
def __repr__(self):
return "User(id=%r, username=%r)" % (self.id, self.username)
# Create tables if not yet created
Base.metadata.create_all(checkfirst=True)
# Turn on echoing so we can see SQL
Base.metadata.bind.echo = True
# A standard session
session = sessionmaker()()
# Clear data
session.query(User).delete()
# Create an user and store it
u1 = User(username='foo', password='foobar')
session.add(u1)
session.commit()
# Password can be checked client side
print u1.password == 'foobar', u1.password == 'asdf'
# And server side
print session.query(User).filter(User.password == 'foobar').all()
print session.query(User).filter(User.password == 'asdf').all()
# Password can be updated
u1.password = 'asdf'
session.flush()
print session.query(User).filter(User.password == 'asdf').all()