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

最新文章

  1. Android搜索功能的案例,本地保存搜索历史记录......
  2. InnoDB与Myisam的六大区别
  3. 本地测试SMTP服务器
  4. 如何在SCENEKIT使用SWIFT RUNTIME动态加载COLLADA文件
  5. android项目的结构和布局
  6. [转]新兵训练营系列课程——平台RPC框架介绍
  7. php网页切图/js切图
  8. svn使用(服务器端和客户端)
  9. nginx/apache/php隐藏http头部版本信息的实现方法
  10. 从Search Sort到Join
  11. 负电压基准电路(-2.5V/-5V电压基准)
  12. Windows - 程序猿应该熟记的CMD常用命令
  13. SOJ 1210 二叉树
  14. Ubuntu 16.04 使用校园网客户端上网
  15. pc端,移动端css重置样式
  16. Linux centos7安装python3并且不影响python2
  17. 解决C#中调用WCF方法报错:远程服务器返回错误 (404) 未找到
  18. JSON 语法
  19. C# 方法参数传递方式 关键字(in、out、ref)
  20. Delphi的自动编译软件Want

热门文章

  1. vue使用--环境搭建与基本项目创建说明
  2. 在Ubuntu18.04.2LTS上遇到的问题汇总
  3. mongodb创建管理员用户
  4. 集成Azure DevOps Server(TFS) 与微软Teams
  5. N!(hdu1042)
  6. SpringDataRedis简单入门介绍
  7. python中easydict的简单使用
  8. 截图自动添加水印图片工具 pickpick设置中文语言
  9. Django学习笔记(14)——AJAX与Form组件知识补充(局部钩子和全局钩子详解)
  10. LocalDB 从2017更换到2014后一直显示连接不正确解决方案