SQLAlchemy和PassLib

kc9*_*jud 5 python passwords hash sqlalchemy pyramid

tl; dr - 在使用SQLAlchemy将密码插入MySQL DB之前,如何使用PassLib等Python端库来密码密码?

好吧,所以我一直在我的桌子上敲我的头一两天试图解决这个问题,所以在这里:

我正在使用Pyramid/SQLAlchemy编写Web应用程序,我正在尝试与MySQL数据库的Users表接口.

最终,我想做以下事情:

将密码与哈希值进行比较:

if user1.password == 'supersecret'
Run Code Online (Sandbox Code Playgroud)

插入新密码:

user2.password = 'supersecret'
Run Code Online (Sandbox Code Playgroud)

我希望能够在进入数据库之前使用PassLib来对我的密码进行哈希处理,而且我不是真的喜欢使用内置的MySQL SHA2功能,因为它没有被腌制.

但是,只是为了尝试它,我确实使用SQL端函数:

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
Run Code Online (Sandbox Code Playgroud)

这是从示例2复制而来的http://www.sqlalchemy.org/trac/wiki/UsageRecipes/DatabaseCrypt

这样可以工作并允许我使用内置的MySQL SHA2功能(通过调用func.sha2())并完全按照我的意愿行事.但是,现在我正在尝试用Python端的PassLib替换它.

PassLib提供了两个功能:一个用于创建新密码哈希,另一个用于验证密码:

from passlib.hash import sha256_crypt

new_password = sha256_crypt.encrypt("supersecret")

sha256_crypt.verify("supersecret", new_password)
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚如何实际实现这一点.阅读完所有文档后,我认为它是TypeDecorator的不同形式,自定义类型声明,混合值或混合属性.我尝试过这样做,但它对我来说没有意义,也没有代码建议实际运行.

那么,总结我的问题 - 如何重载=和==运算符,以便它们通过适当的哈希函数运行?

sap*_*pht 5

PasswordType从SQLAlchemy的-utils的应该是这个问题最合适的.它使用passlib.从文档中删除:

以下用法将创建一个密码列,该列将自动将新密码哈希为pbkdf2_sha512,但仍将密码与预先存在的md5_crypt哈希值进行比较.密码被比较; 数据库中的密码哈希将更新为pbkdf2_sha512.

class Model(Base):
    password = sa.Column(PasswordType(
        schemes=[
            'pbkdf2_sha512',
            'md5_crypt'
        ],
        deprecated=['md5_crypt']
    ))
Run Code Online (Sandbox Code Playgroud)

验证密码非常简单:

target = Model()
target.password = 'b'
# '$5$rounds=80000$H.............'
target.password == 'b'
# True
Run Code Online (Sandbox Code Playgroud)