用户登录应用后,他们的验证状态要记录在用户会话中,这样浏览不同的页面时,才能记住这个状态。Flask-Login扩展用于管理用户身份验证系统中的验证状态,安装:
pip install flask-login
一. User用户模型适配Flask-Login
Flask-login的运转需要应用中有User对象,且必须实现如下的属性和方法:
属性/方法 | 说明 |
is_authenticated | 用户提供的登录凭据有效时返回True |
is_active | 允许用户登录时返回True;禁用账户时可以返回False |
is_anonymous | 普通用户返回False;匿名用户返回True |
get_id() | 返回用户的唯一标识符 |
Flask-Login扩展提供的UserMixin类,包含了以上默认实现,因此可以使User继承自UserMixin:
app/models.py:修改User模型,支持用户登录:
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True)
username = db.Column(db.String(64), unique=True, index=True)
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
password_hash = db.Column(db.String(128))
confirmed = db.Column(db.Boolean, default=False)
这个示例中还添加了email字段,以便使用电子邮件登录应用。
Flask-Login在应用的工厂函数中初始化:
app/__init__.py:初始化Flask-Login
"""定义应用工厂函数"""
...
from flask_login import LoginManager
login_manager = LoginManager()
# 设置登录页面的路由端点
login_manager.login_view = 'auth.login'
def create_app(config_name):
...
login_manager.init_app(app)
...
LoginManager()对象的login_view用于设置登录页面的路由:匿名用户尝试访问受保护页面时,Flask-Login将重定向到登录页面,因此需要将登录页面的路由告知LoginManager()。
最后,Flask-Login还需要指定一个函数,在扩展需要从数据库中获取指定标识符的用户时使用:
app/models.py:加载用户的函数
from . import login_manager
...
@login_manager.user_loader
def load_user(user_id):
"""在Flask-Login需要获取已登录用户的信息时调用"""
return User.query.get(int(user_id))
login_manager.user_loader装饰器把这个函数注册给Flask-Login,在这个扩展需要获取已登录用户的信息时调用。
二. 保护路由
Flask-Login提供的装饰器login_required,可以保护路由,只让通过身份验证的用户访问,未通过身份验证的用户访问这个路由,Flask-Login将拦截请求,把用户发往LoginManager()实例的login_view属性设置的登录页面,用法示例:
from flask-login import login_required
@app.route('/secret')
@login_required
def secret():
return 'Only authenticated users are allowed'
注意:2个装饰器的顺序不允许调换,因为原始函数需要先从login_required接受相关属性,再注册为路由。