用户登入
让我们回顾一下登录视图函数,它实现了一个模拟登录,只发出一个 flash()
消息。 现在,应用可以访问用户数据,并知道如何生成和验证密码哈希值,该视图函数就可以完工了。
# ...
from flask_login import current_user, login_user
from app.models import User
# ...
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('index'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user is None or not user.check_password(form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('index'))
return render_template('login.html', title='Sign In', form=form)
login()
函数中的前两行处理一个非预期的情况:假设用户已经登录,却导航到应用的 /login URL。 显然这是一个不可能允许的错误场景。 current_user
变量来自 Flask-Login,可以在处理过程中的任何时候调用以获取用户对象。 这个变量的值可以是数据库中的一个用户对象(Flask-Login 通过我上面提供的用户加载函数回调读取),或者如果用户还没有登录,则是一个特殊的匿名用户对象。 还记得那些 Flask-Login 必须的用户对象属性? 其中之一是 is_authenticated
,它可以方便地检查用户是否登录。 当用户已经登录,我只需要重定向到主页。
相比之前的调用 flash()
显示消息模拟登录,现在我可以真实地登录用户。 第一步是从数据库加载用户。 利用表单提交的 username,我可以查询数据库以找到用户。 为此,我使用了 SQLAlchemy 查询对象的 filter_by()
方法。 filter_by()
的结果是一个只包含具有匹配用户名的对象的查询结果集。 因为我知道查询用户的结果只可能是有或者没有,所以我通过调用 first()
来完成查询,如果存在则返回用户对象;如果不存在则返回 None。 在 第四章 中,你已经看到当你在查询中调用 all()
方法时, 将执行该查询并获得与该查询匹配的所有结果的列表。 当你只需要一个结果时,通常使用 first()
方法。
如果使用提供的用户名执行查询并成功匹配,我可以接下来通过调用上面定义的 check_password()
方法来检查表单中随附的密码是否有效。 密码验证时,将验证存储在数据库中的密码哈希值与表单中输入的密码的哈希值是否匹配。 所以,现在我有两个可能的错误情况:用户名可能是无效的,或者用户密码是错误的。 在这两种情况下,我都会闪现一条消息,然后重定向到登录页面,以便用户可以再次尝试。
如果用户名和密码都是正确的,那么我调用来自 Flask-Login 的 login_user()
函数。 该函数会将用户登录状态注册为已登录,这意味着用户导航到任何未来的页面时,应用都会将用户实例赋值给 current_user
变量。
然后,只需将新登录的用户重定向到主页,我就完成了整个登录过程。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论