Подтвердить что ты не робот

Реализация Flask-Login с несколькими классами пользователей

Я пишу приложение, в котором есть несколько классов, которые функционируют как пользователи (например, учетная запись School и учетная запись персонала). Я пытаюсь использовать Flask-Login, чтобы сделать это легко, но я не совсем уверен, как это сделать, чтобы, когда пользователь входит в систему, я мог проверить свое приложение, чтобы увидеть, принадлежит ли имя пользователя учетной записи School. или учетную запись персонала, а затем войдите в систему соответствующим образом.

Я знаю, как выяснить, к какому типу аккаунтов он принадлежит (поскольку все имена пользователей должны быть уникальными). Но после этого я не уверен, как сказать приложению, что я хочу, чтобы оно вошло в систему для этого конкретного пользователя.

Прямо сейчас у меня есть только одна универсальная страница входа. Будет ли проще, если я сделаю отдельные страницы входа для учетных записей сотрудников и школ? Я использую базу данных MySQL через Flask-SQLAlchemy.

4b9b3361

Ответ 1

Вы можете определить каждого пользователя с определенной ролью. Например, пользователь "x" может быть SCHOOL, тогда как пользователь "y" может быть "STAFF".

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

Однако флажок-логин не имеет концепции ролей пользователя, и я написал свою собственную версию декодера login_required, чтобы переопределить это. Поэтому вы можете использовать что-то вроде:

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

Затем вы можете использовать этот декоратор для функции вида, например:

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

Ответ 2

@codegeek Я нашел это очень полезным, спасибо. Мне пришлось немного изменить код, чтобы он заработал для меня, поэтому я решил, что я опущу его здесь на тот случай, если он может кому-то помочь:

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

Ответ 3

Это пример того, что вы могли бы сделать. У меня нет опыта использования Flask-SQLAlchemy, но как это не должно быть намного больше. В приведенном ниже примере напрямую используется SQLAlchemy.

Сначала вы определяете класс пользователя, который наследует от Base, чтобы он мог отображаться ORM (декларативный)

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
    }

Как только ваш родительский класс классов готов, установите для каждого из ролей другой класс.

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'
    } 

Использование Flask-Login позволяет вам войти в систему и ограничить доступ на основе ролей.

Вот пример системы входа в систему с двумя разными ролями. Это хороший учебник для фляжки, колба-sqlalchemy, фляжка-логин: http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins

Ответ 4

Взгляните на "Управление ролями" из Flask-Security. Он может быть легко интегрирован с Flask-Login.

Ответ 5

Вариант будет Flask User, как указано в ответе @lv10. Он реализует абстракцию для пользователя, которая обрабатывает множество вещей, одна из которых - аутентификация на основе ролей.

Код в основном останется таким же, как в ответе @codegeek, но свойство "urole" в классе User должно быть переименовано в "role", а роль должна быть классом со свойством "name" (вы можете скопировать и вставить из документации). Вам не нужно определять login_required, так как он уже реализован как role_required. Итак, вместо @login_required(role='rolename') мы имеем @roles_required('rolename').

Я только начал использовать этот API по соображениям безопасности, и это был большой опыт. Я настоятельно рекомендую всем, кто имеет проблемы с паролями, аутентификацией пользователей и ролями пользователей.