2

如何自定义 flask.ext.security.forms.LoginForm 以提示和使用用户名而不是电子邮件?

我试过这个,

class ExtendedLoginForm(LoginForm):
    name = TextField('User Name:', [Required()])
    del LoginForm.email

security = Security(app, user_datastore, login_form=ExtendedLoginForm)

换了模板,

<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
    {{ login_user_form.hidden_tag() }}
    **{{ render_field_with_errors(login_user_form.name) }}**
    {{ render_field_with_errors(login_user_form.password) }}
    {{ render_field_with_errors(login_user_form.remember) }}
    {{ render_field(login_user_form.next) }}
    {{ render_field(login_user_form.submit) }}
</form>

更改了用户db以使用名称而不是电子邮件

但是烧瓶安全仍然尝试在数据存储区而不是用户中查找电子邮件。

4

2 回答 2

1

在早期版本的 flask-security 中,用户的唯一标识符是 email 属性。您可以通过添加自己的属性来扩展模型,但电子邮件字段仍用于唯一标识用户(因此用户名必须是电子邮件字段)。从版本 1.7.0 开始,可以识别具有不同属性的用户。在配置文件中,您应该添加

app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = 'name'

但是您仍然必须在模型中拥有 email 属性。在 git 上报告了 3 天的问题,正是您正在寻找的内容 https://github.com/mattupstate/flask-security/issues/396

于 2015-06-17T12:05:59.963 回答
1

使用名称而不是电子邮件地址登录(使用 Flask-Security 1.7.0 或更高版本),您可以将email字段替换为模型name中的字段User

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(255), unique=True, index=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

并更新app配置。

app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = 'name'

接下来,为了允许用户使用姓名而不是电子邮件登录,我们将使用LoginForm 验证方法假定用户身份属性位于email表单字段中这一事实。

from flask_security.forms import LoginForm
from wtforms import StringField
from wtforms.validators import InputRequired

class ExtendedLoginForm(LoginForm):
    email = StringField('Username', [InputRequired()])

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore,
                    login_form=ExtendedLoginForm)

这样,我们可以使用名称登录,而无需重写验证方法或登录模板。当然,这是一种 hack,更正确的方法是向类添加自定义validate方法(检查name表单字段)ExtendedLoginForm并相应地更新登录模板(如上面 Raja R 所做的那样)。或者更好的是,用 'user_identity' 字段替换 'LoginForm' 中的 'email' 表单字段,并重写 validate 方法以适应任何用户身份字段。

但是,上面的方法可以很容易地使用姓名或电子邮件地址登录。为此,请定义一个包含名称和电子邮件字段的用户模型。

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    name = db.Column(db.String(255), unique=True, index=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))

并更新app配置。

app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('name','email')

最后,创建自定义登录表单。

from flask_security.forms import LoginForm
from wtforms import StringField
from wtforms.validators import InputRequired

class ExtendedLoginForm(LoginForm):
    email = StringField('Username or Email Address', [InputRequired()])

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore,
                    login_form=ExtendedLoginForm)

现在,登录时,Flask-Security 将在电子邮件表单字段中接受电子邮件或姓名。

于 2016-04-29T04:17:57.040 回答