Web 的登录管理是一个比较复杂的过程,之前写过一篇基于 Rest API的登录实现(在这里),最近看到一篇思诚之道写基于 Flask-Login 的实现方法,不由赞叹,示例和讲述写得太棒了,基本是一看就懂,写作方法值得自己好好学习。本文是本人在学习这篇博客时的笔记。
Flask-Login 帮我们做了哪些事?
- Flask-Login 通过 user session,提供登录的常见任务,比如登入 (logging in)、登出 (logging out) 和当前用户 (current user)
-
login_user()
函数:实现用户的登入,一般在登入的视图函数中调用 -
logout_user()
函数:实现登出功能 -
current_user
属性:获取当前用户 - 对于使用者来说,如果需要页面是授权用户才可见,在相应视图函数前加上
@login_required
装饰器进行声明即可,@login_required
装饰器对于未登录用户访问,默认处理是重定向到LoginManager.login_view
所指定的视图
如何使用 Flask-Login ?
1. 定义 User
登录基于用户,需要定义 User 类,Flask-Login 规定 User 类必须实现三个属性和一个方法:
-
is_authenticated
属性 -
is_active
属性 -
is_anonymous
属性 -
get_id()
方法
最简单的方法是从 UserMixin
类继承,该类提供了默认的实现。
# models.py
from flask_login import UserMixin
class User(UserMixin):
pass
users = [
{'id':'Tom', 'username': 'Tom', 'password': '111111'},
{'id':'Michael', 'username': 'Michael', 'password': '123456'}
]
def query_user(user_id):
for user in users:
if user_id == user['id']:
return user
为了简单和便于理解,用户名和密码直接写在代码中。
2. 应用程序的配置
创建 LoginManager
实例,然后与 app 绑定。
from flask_login import LoginManager
login_manager = LoginManager()
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
login_manager.login_message = 'Access denied.'
login_manager.init_app(app)
3. user_loader
回调函数
user session 记录的是用户 ID (user_id),回调函数的作用就是通过 user_id 返回对应的 User 对象。user_loader
回调函数在 user_id 非法的时候不应该抛出异常,而要返回 None。没有这个回调函数的话,Flask-Login 将无法工作
@login_manager.user_loader
def load_user(user_id):
if query_user(user_id) is not None:
curr_user = User()
curr_user.id = user_id
return curr_user
4. 登入功能实现
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
user_id = request.form.get('userid')
user = query_user(user_id)
if user is not None and request.form['password'] == user['password']:
curr_user = User()
curr_user.id = user_id
# 通过Flask-Login的login_user方法登录用户
login_user(curr_user)
return redirect(url_for('index'))
flash('Wrong username or password!')
# GET 请求
return render_template('login.html')
关键就是 login_user(curr_user)
这句代码,之前要构建 User 对象,并指定 id。
5. 登出功能实现
@app.route('/logout')
@login_required
def logout():
logout_user()
return 'Logged out successfully!'
源码
本文源码连接