文章目录
Flask-Login是一个用于处理用户认证和会话管理的Flask插件。它简化了在Flask应用程序中实现用户登录、登出以及保护视图等功能的过程。
一、安装及初始化
pip install flask-login
在flask中进行配置:
from flask import Flask
from flask_login import LoginManager
app = Flask(__name__)
login_manager = LoginManager()
# 初始化LoginManager对象
login_manager.init_app(app)
完成初始化之后,就可以在应用中使用login_manager对象来处理用户认证和会话管理等功能。例如设置用户加载回调函数
保护视图函数等。
二、设置用户加载回调函数
此回调用于从会话中存储的用户ID重新加载用户对象。它应该获取用户的ID,并返回相应的用户对象。例如:
@login_manager.user_loader
def load_user(user_id):
# 根据用户 ID 查询用户对象
user = User.query.get(int(user_id))
return user
三、定义User类
定义 User 类:创建一个 User 类,表示应用程序中的用户,该类需要实现以下几个方法:
-
is_authenticated():返回 True 如果用户已经通过认证,否则返回 False。
-
is_active():返回 True 如果用户是活跃的,否则返回 False。如果用户被禁用,可以返回 False。
-
is_anonymous():返回 True 如果当前用户是匿名用户,否则返回 False。
-
get_id():返回一个唯一标识符的字符串,用于标识用户。
class User:
def init(self, user_id, username, password):
self.id = user_id
self.username = username
self.password = passworddef is_authenticated(self): # 根据你的认证逻辑判断用户是否已经通过认证 return True # 假设用户都已经通过认证 def is_active(self): # 根据你的逻辑判断用户是否是活跃的 return True # 假设所有用户都是活跃的 def is_anonymous(self): # 根据你的逻辑判断当前用户是否是匿名用户 return False # 假设所有用户都不是匿名的 def get_id(self): # 返回一个唯一标识符的字符串,用于标识用户 return str(self.id) @staticmethod def get(user_id): # 从数据库或其他数据源中获取用户对象 # 根据用户 ID 查询用户,并返回 User 对象 # 如果找不到用户,可以返回 None return User(user_id, 'username', 'password')
四、实现登陆操作
login_user(user)会自动调用 User 对象中的 is_authenticated()、is_active() 和 get_id() 方法来判断用户是否通过认证、是否活跃以及获取用户的唯一标识符。
@app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
# 验证表单
if form.validate_on_submit():
login_user(user)
flask.flash('Logged in successfully.')
# 获取名为"next"的查询参数的值
next = flask.request.args.get('next')
# 检查验证给定的URL是否与当前请求的主机和协议匹配,防止跳转到不受信任的主机或使用不安全的协议。
if not url_has_allowed_host_and_scheme(next, request.host):
return flask.abort(400)
return flask.redirect(next or flask.url_for('index'))
return flask.render_template('login.html', form=form)
登陆成功后就可以在模板中使用current_user来获取当前登陆用户了。
{% if current_user.is_authenticated %}
Hi {{ current_user.name }}!
{% endif %}
需要进行登陆验证的视图函数可以使用@login_required修饰器来进行装饰。
也可以使用logout_user()方法来退出登陆。
@app.route("/settings")
@login_required
def settings():
pass
@app.route("/logout")
@login_required
def logout():
logout_user()
return redirect(somewhere)
五、自定义登陆过程
默认情况下,当用户试图在未登录的情况下访问login_required视图时,Flask login会闪烁一条消息,并将其重定向到登录视图。(如果未设置登录视图,它将中止,并显示401错误。)
所以我们需要设置登录页面的视图函数,并指定登录页面的 URL。
# 自定义未登录消息视图
login_manager.login_view = 'login'
# 自定义未登录消息内容
login_manager.login_message = u"Bonvolu ensaluti por uzi tiun paĝon."
# 自定义未登录消息类别
login_manager.login_message_category = "info"
@login_manager.unauthorized_handler 是 Flask-Login 提供的装饰器,用于定义未经授权用户访问受保护页面时的处理方式。
通过此修饰器能够帮助定制未经授权访问的处理方式,以便提供更好的用户体验和安全性。
@login_manager.unauthorized_handler
def unauthorized_callback():
return redirect('/login')
六、使用请求加载器自定义登录
使用请求加载器自定义登录过程。请求加载器允许你根据请求中的信息动态加载用户对象,以满足特定的登录需求。例如获取请求头中的认证信息、查询参数等。
@login_manager.request_loader
def load_user_from_request(request):
# 从请求中获取用户标识,例如获取请求头中的认证信息、查询参数等
user_id = request.headers.get('Authorization')
# 根据用户标识加载用户对象
user = User.query.get(user_id)
return user
七、匿名用户功能
Flask-Login 提供了匿名用户功能,允许你在未登录的情况下访问受保护的页面。匿名用户对象是一个特殊的 UserMixin 对象,它提供了一些默认的属性和方法,可以模拟已登录用户的行为。
-
设置login_manager.anonymous_user属性
login_manager.anonymous_user = Anonymous
-
定义匿名对象Anonymous
定义匿名用户对象
class Anonymous(AnonymousUserMixin):
@property
def is_authenticated(self):
return False
八、记住我功能
"记住我"功能是一种常见的身份验证功能,它允许用户在关闭浏览器后仍然保持登录状态。当用户勾选 "记住我" 选项时,系统会生成一个长期有效的凭证(通常是一个加密的令牌),并在用户下次访问时使用该凭证自动登录用户。
要实现 "记住我" 功能,你可以借助 Flask-Login 提供的 remember_me 参数和相关方法。
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
# 验证用户名和密码,并获取用户 ID
username = request.form['username']
password = request.form['password']
user_id = authenticate(username, password) # 自定义的验证函数
if user_id:
# remember 值为 True/False
remember_me = request.form.get('remember_me')
user = get_user(user_id)
login_user(user, remember=remember_me)
return '登录成功'
else:
return '用户名或密码错误'
return render_template('login.html')
当用户勾选了 "记住我" 选项后,系统会生成一个长期有效的凭证(通常是一个加密的令牌),并在用户下次访问时使用该凭证自动登录用户,无需再次进行登录操作。