Flask的身份验证扩展使用的包和作用列表如下:
1. Werkzeug:计算密码散列值并进行核对
2. Flask-Login:管理已登录用户的用户会话
3. itsdangerous: 生成并核对加密安全令牌
用户登录应用后,他们的验证状态要记录在用户会话中,这样浏览不同的页面时才能记住这个状态 . flask_login是个非常有用的小型扩展,专门用于管理用户身份验证系统中的验证状态,且不依赖特定的身份机制 .
理解Flask-Login的运作方式:
from flask_login import login_user, logout_user, login_required
# 登录路由
@auth.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
next = request.args.get('next')
if next is None or not next.startswith('/'):
next = url_for('main.index')
return redirect(next)
flash('用户名或登录密码无效')
return render_template('auth/login.html', form=form)
# 退出路由
@auth.route('/logout')
@login_required
def logout():
logout_user()
flash('退出登录')
return redirect(url_for('main.index'))
(1) 用户点击“登录”链接,访问登录路由,服务器收到一个没有表单数据的GET请求,validate_on_submit()方法返回值为False, 渲染登录表单;
(2) 用户填写登录表单,输入用户名和密码并提交,服务器收到一个包含数据的POST请求,validate_on_submit()方法调用依附在表单各字段上的验证函数,按顺序依次验证 .
a. 验证通过, validate_on_submit()方法返回值为True, 在数据库中查找相关用户
b. 用户存在且密码验证OK后,调用Flask-Login的login_user()函数登入用户,函数的参数是要登录的用户,和可选的"记住我"布尔值,布尔值为False, 关闭浏览器后用户会话就过期
c. login_user()函数把用户id以字符串的形式写入用户会话
d. 视图函数重定向到首页
(3) 浏览器收到重定向响应, 请求首页
a. 调用首页的视图函数,渲染主页模板
b. 渲染模板的过程中, 首次出现对Flask-Login的current_user的引用(current_user由Flask-Login定义,在视图函数和模板中自动可用)
c. 这个请求还没有给上下文变量current_user赋值, 因此调用Flask-Login内部的_get_user()函数,找出用户是谁
d. _get_user()函数检查用户会话中有没有用户id,没有则返回一个Flask-Login的AnonymousUser实例;如果有,调用应用中使用user_loader装饰器注册的load_user()函数,向其传入字符串形式的用户id
from . import login_manager
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id)) # 将用户id转为整数,传递给Flask-SQLAlchemy查询,加载用户;SQLAlchemy查询执行方法get()返回指定主键对应的行
e. load_user()函数从数据库读取用户,将其返回. Flask-Login把返回的用户对象赋值给当前请求的current_user上下文变量
f. 模板收到新赋值的current_user,生成html页面