我正在使用Flask Login和Principal进行身份和角色管理。我的需求直接来自文档。我的代码在这里:
@identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
# Set the identity user object
identity.user = current_user
# Add the UserNeed to the identity
if hasattr(current_user, 'get_id'):
print 'current_user ' + str(current_user.get_id())
identity.provides.add(UserNeed(current_user.get_id))
# Assuming the User model has a list of roles, update the
# identity with the roles that the user provides
if hasattr(current_user, 'roles'):
if current_user.roles:
for role in current_user.roles:
identity.provides.add(RoleNeed(role.name))
在我的登录代码中,我这样做:
identity_changed.send(current_app._get_current_object(),
identity=Identity(user.user_id)
登录时,信号会按预期触发。在每个后续页面加载时,current_user是匿名的,并且没有用户ID,但所有@login_required函数的行为就像用户登录一样.Flask登录知道用户已登录,但由于某种原因,current_user不一致。
我错过了某处的重要配置点吗?
答案 0 :(得分:6)
我遇到了同样的问题!根本原因是Flask-Login和Flask-Principal在请求的“预处理”阶段按Flask应用程序注册的顺序由Flask调用。如果您在注册Flask-Login之前注册Flask-Principal,那么@identity_loaded.connect_via(app)
将在@login_manager.user_loader
之前调用,因此current_user将返回匿名用户。
Flask-Principal文档示例显示了a code excerpt,其中Flask-Principal在 Flask-Login之前注册了。 Tsk tsk!这是我最终在我的引导程序中做的事情:
login_manager = LoginManager()
login_manager.init_app(app)
# ...
principals = Principal(app) # This must be initialized after login_manager.
然后在我的users.py视图文件中:
@identity_loaded.connect_via(app)
def on_identity_loaded(sender, identity):
""" This function is called by Flask-Principal after a user logs in. """
identity.user = current_user
if isinstance(current_user, User):
identity.provides.add(UserNeed(current_user.id))
for permission in user.permissions:
# Do permission-y stuff here.
这解决了我的问题。
编辑:我已将a bug report提交给项目以获取文档。
答案 1 :(得分:0)
谢谢您,这是一个有用的相关观察。我一直在努力解决类似的问题,即用户角色在登录后无法持久保存在后续请求中。作为一个初学者,并与flask-user(我从没工作过)一起玩,并选择a)flask-principal和flask-login,以及b)flask-navigation而不是flask-nav。
这是这样我就可以1)容易地控制哪些菜单项出现基于具有导航标记产生的模板的外部委托和2)避免(为我总是教导要分离的逻辑和演示和写入为定制菜单渲染器如果我以后要更改HTML,那只用于更改周围HTML的flask-nav似乎并不正确。我找不到一种方法来遍历flask-nav对象或向nav项目添加自定义属性,而在flask-navigation中,我创建了一个自定义Item来扩展flask-navigation的Item以添加所需的权限。
我也试图解决为具有角色的层次结构,以防止不必把复杂的权限声明中我的观点的挑战(例如,管理员也编辑,也是用户,也是匿名用户等)已经疯狂地用Google搜索我找不到像这样的层次结构的任何概念。我也不希望在模型中为用户分配多个角色。
我的错误是:
#CAVEATS - still learning Flask so this may not be the right approach and it is still a W.I.P.
#added a kind of hierarchy order field to User to drive multiple roles in Permissions
#with this model I only have to assign one role to a user
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), unique=True)
description = db.Column(db.String(200))
hierarchy_order = db.Column(db.Integer)
internal = db.Column(db.Boolean) # this is only so I can identify registered users and internal users
users = db.relationship('User', backref='role',lazy='dynamic')
def __repr__(self):
return '<Role: {}>'.format(self.name)
# changed common flask-login example @login_manager.user_loader as follows
@login_manager.user_loader
def load_user(user_id):
user = User.query.get(int(user_id))
#work out what roles are below current role
permissable_roles = Role.query.filter(Role.hierarchy_order<=user.role.hierarchy_order).all()
user.roles = permissable_roles
return user
我倒是十分想拥有这种方法作为通用惯例,但我觉得我坚持用具有@ login_manager.user_loader其中的多个角色都分配从分配的角色下工作层次的循环。我希望其中一些可以帮助某人努力将它们联系在一起。我还有很多东西需要学习什么地方时,在不同的上下文中才能使用它们烧瓶商店的东西,。