Flask Login and Principal – current_user es anónimo aunque estoy conectado

Estoy usando Flask Login y Principal para la gestión de identidades y roles. Mis necesidades se describen directamente de la documentación. Mi código está aquí:

@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)) 

En mi código de inicio de sesión hago esto:

 identity_changed.send(current_app._get_current_object(), identity=Identity(user.user_id) 

Al iniciar sesión, la señal se dispara como se esperaba. En cada carga de página subsiguiente, current_user es anónimo y aún no tiene el ID de usuario. Todas las funciones de @login_required se comportan como si el usuario hubiera iniciado sesión. El inicio de sesión en el flask sabe que el usuario ha iniciado sesión, pero por alguna razón el current_user es inconsistente.

¿Me falta un punto de configuración esencial en alguna parte?

    ¡Encontré el mismo problema! La causa principal es que Flask-Login y Flask-Principal son invocados por Flask durante la etapa de “preprocesamiento” de la solicitud en el orden en que se registraron con su aplicación Flask . Si registra Flask-Principal antes de registrar Flask-Login, se llamará a @identity_loaded.connect_via(app) antes de @login_manager.user_loader , y current_user devolverá al usuario anónimo.

    El ejemplo de documentación de Flask-Principal muestra un extracto de código en el que Flask-Principal se registra antes de Flask-Login. Tsk tsk! Esto es lo que terminé haciendo en mi bootstrap:

     login_manager = LoginManager() login_manager.init_app(app) # ... principals = Principal(app) # This must be initialized after login_manager. 

    Luego en mi users.py ver archivo:

     @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. 

    Esto resolvió mi problema.

    Edición: envié un informe de error al proyecto para la documentación.

    Gracias por esto, aquí hay una observación relacionada en caso de que sea útil. He estado luchando con un problema similar de roles de usuario que no persisten en solicitudes posteriores después de iniciar sesión. Siendo un principiante, y jugando con diferentes cosas como flask-user (que nunca conseguí trabajar) y estableciendo en a) flask-principal y flask-login yb) flask-navigation en lugar de flask-nav.

    Esto es para que pueda 1) controlar fácilmente qué elementos del menú aparecen en función de Principal y 2) evitar tener el marcado de navegación generado fuera de una plantilla (ya que siempre me enseñaron a separar la lógica y la presentación y escribir un renderizador de menú personalizado para flask-nav solo para cambiar el HTML circundante no me pareció correcto si quiero cambiar el HTML más adelante). No pude encontrar una manera de recorrer los objetos de flask-nav o agregar propiedades personalizadas a los elementos de navegación mientras que en flask-navigation estoy creando un elemento personalizado que extiende el elemento de flask-navigation para agregar los permisos necesarios.

    El desafío que también intentaba resolver era tener una jerarquía de roles para evitar tener que incluir en mi opinión declaraciones de Permiso complejas (por ejemplo, Admin también es editor, también es usuario, también es usuario anónimo, etc.) Haber buscado en Google con furia no pude Encuentra cualquier concepto de jerarquía así. Tampoco quiero particularmente tener múltiples roles asignados a un usuario en mi modelo.

    Mis errores fueron:

    • Lo anterior en el orden de carga.
    • Como aún no había puesto roles en mis modelos, de modo que, en mi ignorancia, existía una relación de muchos a muchos entre ellos, no me di cuenta de que Flask-Login necesitaba cargar los roles en la función @ login_manager.user_loader si el roles donde todavía no están en el modelo. En su lugar, asigné los roles en la vista de inicio de sesión después de login_user (usuario) antes de emitir la señal del flask-principal.
    • Con mi enfoque diferente, los roles se asignaron, pero se olvidaron en la siguiente solicitud. Este post me dio las pistas que estaba buscando. Esto es lo que terminé haciendo: todos los demás códigos relacionados con el Principal son los que aparecen en los documentos y más arriba.
     #CAVEATS - still learning Flask so this may not be the right approach and it is still a WIP #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 ''.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 

    Me encantaría tener este enfoque como una convención común, pero creo que me quedo con tener un bucle en @ login_manager.user_loader que asigna los múltiples roles como una jerarquía que funciona desde el rol asignado. Espero que algo de esto ayude a alguien que lucha con la forma en que todo se une. Todavía tengo mucho que aprender acerca de dónde almacena las cosas el matraz y cuándo están disponibles en diferentes contextos.