Python 通过用户名而不是电子邮件进行安全登录
我想在Python 通过用户名而不是电子邮件进行安全登录,python,flask,flask-security,Python,Flask,Flask Security,我想在用户模型中设置一个字段,用户通过该字段以用户名的身份登录,而不是电子邮件 我定义: app.config['SECURITY\u USER\u IDENTITY\u ATTRIBUTES']=“username” 但我仍然得到: user_datastore.add_role_to_user(name, 'mgmt') File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/fla
用户
模型中设置一个字段,用户通过该字段以用户名
的身份登录,而不是电子邮件
我定义:app.config['SECURITY\u USER\u IDENTITY\u ATTRIBUTES']=“username”
但我仍然得到:
user_datastore.add_role_to_user(name, 'mgmt')
File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/flask_security/datastore.py", line 105, in add_role_to_user
user, role = self._prepare_role_modify_args(user, role)
File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/flask_security/datastore.py", line 72, in _prepare_role_modify_args
user = self.find_user(email=user)
File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/flask_security/datastore.py", line 203, in find_user
return self.user_model.query.filter_by(**kwargs).first()
File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/sqlalchemy/orm/query.py", line 1333, in filter_by
for key, value in kwargs.items()]
File "/Users/boazin/sentinal/sentinel-cloud/.env/lib/python2.7/site-packages/sqlalchemy/orm/base.py", line 383, in _entity_descriptor
(description, key)
InvalidRequestError: Entity '<class 'flask_app.models.User'>' has no property 'email'
从
字段id、电子邮件、密码、活动的是必需的。因此添加
email = db.Column(db.String(255), unique=True)
只需在此基础上添加自定义的用户名
字段。要使用用户名而不是电子邮件地址登录(使用Flask Security 1.7.0或更高版本),您可以在用户
模型中将电子邮件
字段替换为用户名
字段
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = 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'] = 'username'
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('username','email')
接下来,为了允许用户使用用户名而不是电子邮件登录,我们将使用这样一个事实,即假定用户标识属性位于email
form字段中
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)
这样,我们可以使用用户名登录,而无需重写验证方法或登录模板。当然,这是一种黑客行为,更正确的方法是向ExtendedLoginForm
类添加一个自定义的validate
方法,该方法检查username
表单字段,并相应地更新登录模板
然而,上述方法使得使用用户名或电子邮件地址登录变得容易。为此,请使用用户名和电子邮件字段定义一个用户模型
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
username = 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'] = 'username'
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('username','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将在电子邮件表单字段中接受电子邮件或用户名。我通过覆盖登录表单实现了使用用户名或密码登录:
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)
class ExtendedLoginForm(LoginForm):
email = StringField('Username or Email Address')
username = StringField("Username")
def validate(self):
from flask_security.utils import (
_datastore,
get_message,
hash_password,
)
from flask_security.confirmable import requires_confirmation
if not super(LoginForm, self).validate():
return False
# try login using email
self.user = _datastore.get_user(self.email.data)
if self.user is None:
self.user = _datastore.get_user(self.username.data)
if self.user is None:
self.email.errors.append(get_message("USER_DOES_NOT_EXIST")[0])
# Reduce timing variation between existing and non-existing users
hash_password(self.password.data)
return False
if not self.user.password:
self.password.errors.append(get_message("PASSWORD_NOT_SET")[0])
# Reduce timing variation between existing and non-existing users
hash_password(self.password.data)
return False
if not self.user.verify_and_update_password(self.password.data):
self.password.errors.append(get_message("INVALID_PASSWORD")[0])
return False
if requires_confirmation(self.user):
self.email.errors.append(get_message("CONFIRMATION_REQUIRED")[0])
return False
if not self.user.is_active:
self.email.errors.append(get_message("DISABLED_ACCOUNT")[0])
return False
return True
并按照其他帖子中的描述进行注册:
# Setup Flask-Security
app.config['SECURITY_USER_IDENTITY_ATTRIBUTES'] = ('username','email')
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore,
login_form=ExtendedLoginForm)
由于电子邮件和用户名是可选的,现在可以使用其中一个进行登录。但是要确保这两个字段在数据库模型中都设置为唯一的。addusername=DB.Column(DB.String(255),unique=True)
发送给您的型号用户
很明显我有一个……您可以发布flask\u应用程序型号吗。User@itzmeontv-使用模型编辑原始问题,我在电子邮件字段中输入什么?如果不想使用,可以设置虚拟电子邮件