这篇文章介绍了 flask-login 是如何实现一个不需要使用数据库的用户认证组件的。
flask-login 的基本使用
在介绍 flask-login 的工作原理之前先来简要回顾一下 flask-login 的使用方法。
首先要创建一个 LoginManager
的实例并注册在 Flask
实例上,然后提供一个 user_loader
回调函数来根据会话中存储的用户 ID 来加载用户对象。
login_manager = LoginManager()
login_manager.init_app(app)
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
flask-login 还要求你对数据对象做一些改动,添加以下属性和方法:
@property
def is_active(self):
return True
@property
def is_authenticated(self):
return True
@property
def is_anonymous(self):
return False
#: 这个方法返回一个能够识别唯一用户的 ID
def get_id(self):
try:
return text_type(self.id)
except AttributeError:
raise NotImplementedError('No `id` attribute - override `get_id`')
完成这些设置工作之后,就可以使用 flask-login 了,一些典型的用法包括登录和登出用户:login_user(user)
及 logout_user()
,及使用 @login_required
保护一些视图函数,检测当前用户是否有访问的权限(根据是否认证进行区别):
@app.route("/settings")
@login_required
def settings():
pass
以及通过 current_user
对象来访问当前用户。
flask-login 源码解析
我们按照使用过程中调用 flask-login 的顺序来解析其源码。
LoginManager 对象
先来看 LoginManager
对象,它用于记录所有的配置信息,其 __init__
方法中初始化了这些配置信息。一个 LoginManager
对象通过 init_app 方法注册到 Flask 实例上:
def init_app(self, app, add_context_processor=True):
app.login_manager = self
app.after_request(self._update_remember_cookie)
self._login_disabled = app.config.get('LOGIN_DISABLED', False)
if add_context_processor:
app.context_processor(_user_context_processor)
这个方法的主要工作是在 Flask 实例的 after_request 钩子上添加了一个用户更新 remember_me cookie 的函数,并在 Flask 的上下文处理器中添加了一个用户上下文处理器。
def _user_context_processor():
return dict(current_user=_get_user())
这个上下文处理器设置了一个全局可访问的变量 current_user
,这样我们就可以在视图函数或者模板文件中访问这个变量了。
user_loader 修饰器
然后就到了这个方法,它是 LoginManager 的实例方法,把 user_callback 设置成我们传入的函数,在实际的使用过程中,我们是通过修饰器传入这个函数的ÿ