Flask-Login中装饰器@login_manager.user_loader的作用及原理
2024-09-08 15:04:38
Flask-Login通过装饰器@login_required来检查访问视图函数的用户是否已登录,没有登录时会跳转到login_manager.login_view = 'auth.login'所注册的登录页。登录时即需调用login_user()函数,而在内部调用了由我们注册的回调函数。
Flask-Login就是通过装饰器,来注册回调函数,当没有sessionID时,通过装饰器指定的函数来读取用户到session中,达到在前端模板中调用当前登录用户current_user的目的,该装饰器就是:
@login_manager.user_loader
其功能类似如下
class Test():
# 在Test中并没有真正的定义callback
def feature(self):
self.callback() def decorate(self, func):
self.callback=func
return func test = Test() # 将fun注册为回调函数
@test.decorate
def fun():
print(1) # 调用feature将触发回调函数
test.feature() #
装饰器user_loader:
def user_loader(self, callback):
'''
This sets the callback for reloading a user from the session. The
function you set should take a user ID (a ``unicode``) and return a
user object, or ``None`` if the user does not exist. :param callback: The callback for retrieving a user object.
:type callback: callable
'''
self.user_callback = callback
return callback
这个装饰器的目的即将回调函数赋给self.user_callback
在login_user函数内部:
user_id = getattr(user, current_app.login_manager.id_attribute)()
session['user_id'] = user_id # 在这里设置用户id
session['_fresh'] = fresh
session['_id'] = current_app.login_manager._session_identifier_generator() if remember:
session['remember'] = 'set'
if duration is not None:
try:
# equal to timedelta.total_seconds() but works with Python 2.6
session['remember_seconds'] = (duration.microseconds +
(duration.seconds +
duration.days * 24 * 3600) *
10**6) / 10.0**6
except AttributeError:
raise Exception('duration must be a datetime.timedelta, '
'instead got: {0}'.format(duration)) _request_ctx_stack.top.user = user
user_logged_in.send(current_app._get_current_object(), user=_get_user())
调用时将user的属性写入session,并绑定到当前的请求上下文。由于HTTP是无状态的,每次发起新请求时flask会创建一个请求上下文,在分发路由时flask-login根据cookie判断用户并绑定到当前的请求上下文,由于这种绑定关系的存在,那么每次新的请求发生时都需要获取user看一下最后绑定的代码:
def reload_user(self, user=None):
ctx = _request_ctx_stack.top if user is None:
user_id = session.get('user_id')
if user_id is None:
ctx.user = self.anonymous_user()
else:
if self.user_callback is None:
raise Exception(
"No user_loader has been installed for this "
"LoginManager. Add one with the "
"'LoginManager.user_loader' decorator.")
user = self.user_callback(user_id)
if user is None:
ctx.user = self.anonymous_user()
else:
ctx.user = user
else:
ctx.user = user
这个函数即未获得user时调用的,这时就必须调用回调函数self.user_callback
自己定义的回调函数:
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
self.user_callback就是装饰器装饰的回调函数load_user(),reload_user的作用就是当user无值时调用该方法获取user并绑定到当前的请求上下文,绑定的意义在于每次当我们使用current_user的时候,会直接从当前上下文中返回。
装饰器login_required:
def login_required(func): @wraps(func)
def decorated_view(*args, **kwargs):
if current_app.login_manager._login_disabled:
return func(*args, **kwargs)
elif not current_user.is_authenticated:
return current_app.login_manager.unauthorized()
return func(*args, **kwargs)
return decorated_view
最新文章
- Android搜索功能的案例,本地保存搜索历史记录......
- InnoDB与Myisam的六大区别
- 本地测试SMTP服务器
- 如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件
- android项目的结构和布局
- [转]新兵训练营系列课程——平台RPC框架介绍
- php网页切图/js切图
- svn使用(服务器端和客户端)
- nginx/apache/php隐藏http头部版本信息的实现方法
- 从Search Sort到Join
- 负电压基准电路(-2.5V/-5V电压基准)
- Windows - 程序猿应该熟记的CMD常用命令
- SOJ 1210 二叉树
- Ubuntu 16.04 使用校园网客户端上网
- pc端,移动端css重置样式
- Linux centos7安装python3并且不影响python2
- 解决C#中调用WCF方法报错:远程服务器返回错误 (404) 未找到
- JSON 语法
- C# 方法参数传递方式 关键字(in、out、ref)
- Delphi的自动编译软件Want