Implementando Flask-Login con múltiples clases de usuarios

Estoy escribiendo una aplicación que tiene varias clases que funcionan como usuarios (por ejemplo, una cuenta escolar y una cuenta del personal). Estoy tratando de usar Flask-Login para que esto sea fácil, pero no estoy muy seguro de cómo hacerlo, de modo que cuando un usuario inicia sesión puedo hacer que mi aplicación verifique si el nombre de usuario pertenece a una cuenta de School o Cuenta de personal, y luego inicie sesión apropiadamente.

Sé cómo averiguar a qué tipo de cuenta pertenece (ya que todos los nombres de usuario deben ser únicos). Pero después de eso no estoy seguro de cómo decirle a la aplicación que deseo que inicie sesión en ese usuario específico.

En este momento, solo tengo una página de inicio de sesión universal. ¿Es más fácil si hago páginas de inicio de sesión separadas para las cuentas del personal y las de la escuela? Estoy usando una base de datos MySQL a través de Flask-SQLAlchemy.

Puede definir cada usuario con un rol específico. Por ejemplo, el usuario ‘x’ puede ser ESCUELA mientras que el usuario ‘y’ puede ser ‘PERSONAL’.

class User(db.Model): __tablename__ = 'User' id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(80),unique=True) pwd_hash = db.Column(db.String(200)) email = db.Column(db.String(256),unique=True) is_active = db.Column(db.Boolean,default=False) urole = db.Column(db.String(80)) def __init__(self,username,pwd_hash,email,is_active,urole): self.username = username self.pwd_hash = pwd_hash self.email = email self.is_active = is_active self.urole = urole def get_id(self): return self.id def is_active(self): return self.is_active def activate_user(self): self.is_active = True def get_username(self): return self.username def get_urole(self): return self.urole 

Sin embargo, Flask-login todavía no tiene el concepto de roles de usuario y escribí mi propia versión de decorador login_required para anular eso. Así que quizás quieras usar algo como:

 def login_required(role="ANY"): def wrapper(fn): @wraps(fn) def decorated_view(*args, **kwargs): if not current_user.is_authenticated(): return current_app.login_manager.unauthorized() urole = current_app.login_manager.reload_user().get_urole() if ( (urole != role) and (role != "ANY")): return current_app.login_manager.unauthorized() return fn(*args, **kwargs) return decorated_view return wrapper 

Luego, puedes usar este decorador en una función de vista como:

 @app.route('/school/') @login_required(role="SCHOOL") def restricted_view_for_school(): pass 

@codegeek me pareció muy útil, gracias. Tuve que modificar el código un poco para que funcionara, así que pensé que lo dejaría aquí en caso de que pudiera ayudar a alguien más:

 from functools import wraps login_manager = LoginManager() ... def login_required(role="ANY"): def wrapper(fn): @wraps(fn) def decorated_view(*args, **kwargs): if not current_user.is_authenticated(): return login_manager.unauthorized() if ((current_user.role != role) and (role != "ANY")): return login_manager.unauthorized() return fn(*args, **kwargs) return decorated_view return wrapper 

Este es un ejemplo de lo que podrías hacer. No tengo experiencia en el uso de Flask-SQLAlchemy, pero el cómo no debería ser mucho más diferente. El siguiente ejemplo usa SQLAlchemy directamente.

Primero, define una clase de usuario que hereda de la Base para que pueda ser mapeada por ORM (Declarativo)

 class User(Base): __tablename__ = 'user_table' id = Column(Integer, primary_key=True) email = Column(String(45), unique=True) name = Column(String(45)) pwd = Column(String(8)) user_role = Column(String(15)) __mapper_args__ = { 'polymorphic_identity': 'user_table', 'polymorphic_on': user_role } 

Una vez que su clase de clase principal esté lista, establezca una clase diferente para cada uno de los roles que desea tener.

 class SchoolAccount(User): __tablename__ = 'school_account' id = Column(Integer, ForeignKey('user_table.id'), primary_key=True) representative_name = Column(String(45)) __mapper_args__ = { 'polymorphic_identity': 'school_account' } 

Usando Flask-Login, inicia sesión con el usuario y limita el acceso en función de los roles.

Aquí hay un ejemplo de un sistema de inicio de sesión con dos roles diferentes. Este es un buen tutorial para flask, flask-sqlalchemy, flask-login: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins

Eche un vistazo a “Gestión de roles” de Flask-Security . Se puede integrar fácilmente con Flask-Login.

Una opción sería el usuario Flask como lo menciona la respuesta @ lv10. Implementa una abstracción para el usuario que maneja muchas cosas, una de ellas es la autenticación basada en roles .

El código seguirá siendo básicamente el mismo que en la respuesta de @codegeek, pero la propiedad “urole” en la clase Usuario debe cambiarse a “roles” y el rol debe ser una clase con la propiedad “nombre” (puede copiar y pegar desde la documentación ). No necesitará definir login_required, ya que ya está implementado como roles_required. Entonces, en lugar de @login_required(role='rolename') tenemos @roles_required('rolename') .

Acabo de empezar a usar esta API por razones de seguridad y es una gran experiencia. Recomiendo encarecidamente a cualquier persona con problemas con contraseñas, autenticación de usuarios y roles de usuario.