假设我有一个用户模型,例如:
class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(255))
    last_name = db.Column(db.String(255))
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    registered_on = db.Column(db.DateTime, nullable=True)
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
和管理员视图:
class UserView(MyModelView):
    form_columns = (
        'roles',
        'first_name',
        'last_name',
        'email',
        'password',
        'registered_on',
    )
    form_args = dict(
                registered_on=dict(default=datetime.now())
            )
当我创建一个新用户时,如何使用 bcrypt 之类的东西自动生成密码哈希?
Cau*_*ons 10
我发现的最简单的选择是添加一个SQLAlchemy 属性事件,User.password并在更改时散列密码。这样,无论何时从任何地方更改用户密码,它都会被自动散列。
from sqlalchemy import event
from werkzeug.security import generate_password_hash
@event.listens_for(User.password, 'set', retval=True)
def hash_user_password(target, value, oldvalue, initiator):
    if value != oldvalue:
        return generate_password_hash(value)
    return value
我认为自动是指它应该自动将手动提供的纯文本密码转换为哈希,但我不确定。我的回答好像这个假设是正确的。
我们不会在 Flask-Admin 中公开我们的密码字段,但我们通过定义password一个属性来处理密码如何以及何时被散列的基本问题,setter 负责计算散列本身并将其隐藏在user._password.
天真地尝试password在管理视图中添加为列是行不通的,但是如果您使用 sqlalchemy 的hybrid_property而不是property,看起来这"password"在您的用户视图的列表中可以正常工作form_columns(因为您已经有了):
# models.py
from sqlalchemy.ext.hybrid import hybrid_property
class User(sql.Model):
    # ...
    _password = sql.Column(sql.Binary)
    _salt = sql.Column(sql.Binary, default=lambda: os.urandom(512))
    # ... 
    @hybrid_property
    def password(self):
        """Return the hashed user password."""
        return self._password
    @password.setter
    def password(self, new_pass):
        """Salt/Hash and save the user's new password."""
        new_password_hash = compute_new_password_hash(new_pass, self._salt)
        self._password = new_password_hash
# admin.py
class UserView(MyModelView):
    # ...
    form_columns = ("email", "password", ...)
编辑体验并没有完全完善——您可能需要覆盖该字段以对其进行优化。以下是一些截图:
使用预设密码创建新用户:
创建后的编辑视图:
更新用户密码:
保存新密码后的编辑视图: