Note that there are some explanatory texts on larger screens.

plurals
  1. POSQLAlchemy & PassLib
    primarykey
    data
    text
    <p><strong><em>tl;dr -- How do I use a Python-side library such as PassLib to hash passwords before inserting them into a MySQL DB with SQLAlchemy?</em></strong> </p> <p>Alright, so I've been banging my head on my desk for a day or two trying to figure this out, so here it goes:</p> <p>I am writing a web application using Pyramid/SQLAlchemy and I'm trying to interface with my MySQL database's Users table. </p> <p>Ultimately, I want to do something like the following:</p> <p>Compare a password to the hash: </p> <pre class="lang-python prettyprint-override"><code>if user1.password == 'supersecret' </code></pre> <p>Insert a new password:</p> <pre class="lang-python prettyprint-override"><code>user2.password = 'supersecret' </code></pre> <p>I'd like to be able to use PassLib to hash my passwords before they go to the database, and I'm not really a fan of using the built-in MySQL SHA2 function since it's not salted.</p> <p>However, just to try it, I do have this working using the SQL-side function:</p> <pre class="lang-python prettyprint-override"><code>from sqlalchemy import func, TypeDecorator, type_coerce from sqlalchemy.dialects.mysql import CHAR, VARCHAR, INTEGER from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column class SHA2Password(TypeDecorator): """Applies the SHA2 function to incoming passwords.""" impl = CHAR(64) def bind_expression(self, bindvalue): return func.sha2(bindvalue, 256) class comparator_factory(CHAR.comparator_factory): def __eq__(self, other): local_pw = type_coerce(self.expr, CHAR) return local_pw == func.sha2(other, 256) class User(Base): __tablename__ = 'Users' _id = Column('userID', INTEGER(unsigned=True), primary_key=True) username = Column(VARCHAR(length=64)) password = Column(SHA2Password(length=64)) def __init__(self, username, password): self.username = username self.password = password </code></pre> <p>This was copied from the example 2 at <a href="http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DatabaseCrypt" rel="nofollow noreferrer">http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DatabaseCrypt</a></p> <p>So that works and allows me to use the built-in MySQL SHA2 function (by calling <code>func.sha2()</code>) and do exactly what I want. However, now I'm trying to replace this with PassLib on the Python side. </p> <p>PassLib presents two functions: one to create a new password hash, and one to verify a password:</p> <pre class="lang-python prettyprint-override"><code>from passlib.hash import sha256_crypt new_password = sha256_crypt.encrypt("supersecret") sha256_crypt.verify("supersecret", new_password) </code></pre> <p>I can't quite figure out how to actually implement this. Having read all the documentation, I think it is either a different form of TypeDecorator, a custom type declaration, a hybrid value, or a hybrid property. I tried following <a href="https://stackoverflow.com/questions/12212636/sql-alchemy-overriding">this</a>, but it doesn't really make sense to me nor does the code suggested there actually run.</p> <p>So, to sum up my question -- how do I overload the <code>=</code> and <code>==</code> operators so that they run things through the appropriate hash functions?</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload