python - SQLAlchemy 和通行证库

标签 python hash passwords sqlalchemy pyramid

tl;dr -- 在使用 SQLAlchemy 将密码插入 MySQL 数据库之前,如何使用 Python 端库(例如 PassLib)对密码进行哈希处理?

好吧,我已经用头在 table 上敲了一两天试图解决这个问题,所以就这样吧:

我正在使用 Pyramid/SQLAlchemy 编写一个 Web 应用程序,并且我正在尝试与我的 MySQL 数据库的用户表进行交互。

最终,我想做如下事情:

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

if user1.password == 'supersecret'

输入新密码:

user2.password = 'supersecret'

我希望能够在密码进入数据库之前使用 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

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

这样就可以使用内置的 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)

我不太清楚如何实际实现它。阅读了所有文档后,我认为它要么是 TypeDecorator 的不同形式,要么是自定义类型声明,要么是混合值,要么是混合属性。我尝试关注 this ,但这对我来说并没有真正意义,那里建议的代码也没有实际运行。

所以,总结一下我的问题——如何重载 === 运算符,以便它们通过适当的哈希函数运行?

最佳答案

PasswordType来自 sqlalchemy-utils应该最适合这个问题。它使用 passlib。从文档中截取:

The following usage will create a password column that will automatically hash new passwords as pbkdf2_sha512 but still compare passwords against pre-existing md5_crypt hashes. As passwords are compared; the password hash in the database will be updated to be pbkdf2_sha512.

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

Verifying password is as easy as:

target = Model()
target.password = 'b'
# '$5$rounds=80000$H.............'
target.password == 'b'
# True

关于python - SQLAlchemy 和通行证库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14968300/

相关文章:

c++ - knuth 乘法哈希

python - Python 如何将 2 个对象视为不相等且不相同,但具有相同的 ID?

c++ - Windows 有默认的单词词典吗?

php - 你能帮我理解盐散列函数吗?

java - 在 JTextFIeld 中隐藏/显示密码 (Java Swing)

python - Scrapy 项目管道并行或顺序执行 process_item

python - 列表上正则表达式过滤器后输出中的分隔符

python - 在 python 中使用后缀树

python - ZeroMQ 没有收到客户端程序发送的值

python - 根据索引获取行,然后创建另一个单独的数据框