假设我有一个用户模型,例如:
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'))
Run Code Online (Sandbox Code Playgroud)
和管理员视图:
class UserView(MyModelView):
form_columns = (
'roles',
'first_name',
'last_name',
'email',
'password',
'registered_on',
)
form_args = dict(
registered_on=dict(default=datetime.now())
)
Run Code Online (Sandbox Code Playgroud)
当我创建一个新用户时,如何使用 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
Run Code Online (Sandbox Code Playgroud)
我认为自动是指它应该自动将手动提供的纯文本密码转换为哈希,但我不确定。我的回答好像这个假设是正确的。
我们不会在 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", ...)
Run Code Online (Sandbox Code Playgroud)
编辑体验并没有完全完善——您可能需要覆盖该字段以对其进行优化。以下是一些截图:
使用预设密码创建新用户:
创建后的编辑视图:
更新用户密码:
保存新密码后的编辑视图: