Python 使用多个用户类实现Flask登录

Python 使用多个用户类实现Flask登录,python,flask,flask-sqlalchemy,flask-login,Python,Flask,Flask Sqlalchemy,Flask Login,我正在编写一个应用程序,它有多个类作为用户使用(例如,一个学校帐户和一个员工帐户)。我正在尝试使用Flask登录来简化这一过程,但我不太确定如何做到这一点,因此当用户登录时,我可以让我的应用程序检查用户名是否属于学校帐户或员工帐户,然后适当地登录 我知道如何确定它属于哪种类型的帐户(因为所有用户名都必须是唯一的)。但在那之后,我不知道如何告诉应用程序我想让它登录到那个特定的用户 现在,我只有一个通用登录页面。如果我为员工帐户和学校帐户创建单独的登录页面,会更容易吗?我通过Flask SQLAlc

我正在编写一个应用程序,它有多个类作为用户使用(例如,一个学校帐户和一个员工帐户)。我正在尝试使用Flask登录来简化这一过程,但我不太确定如何做到这一点,因此当用户登录时,我可以让我的应用程序检查用户名是否属于学校帐户或员工帐户,然后适当地登录

我知道如何确定它属于哪种类型的帐户(因为所有用户名都必须是唯一的)。但在那之后,我不知道如何告诉应用程序我想让它登录到那个特定的用户


现在,我只有一个通用登录页面。如果我为员工帐户和学校帐户创建单独的登录页面,会更容易吗?我通过Flask SQLAlchemy使用MySQL数据库

这是一个你可以做的例子。我没有使用炼金术的经验,但是怎么做应该不会有太大的不同。下面的示例直接使用SQLAlchemy

首先定义一个从
Base
继承的用户类,以便可以通过ORM(声明性)对其进行映射

一旦您的父类准备就绪,为您想要拥有的每个角色设置一个不同的类

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登录可以登录用户并根据角色限制访问


下面是一个具有两个不同角色的登录系统示例。这是一个关于flask、flask sqlalchemy、flask登录的很好的教程:

您可以用特定的角色定义每个用户。例如,用户“x”可以是学校,而用户“y”可以是员工

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
然而,Flask login还没有用户角色的概念,我编写了自己版本的login\u required decorator来覆盖它。因此,您可能需要使用以下内容:

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

@我觉得这个很有用,谢谢。我不得不对代码进行一些修改以使其适合我,因此我想我会将其放在这里,以防它可以帮助其他人:

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
请从中查看“角色管理”。它可以很容易地与Flask登录集成

选项如@10级答案所述。它实现了一个对用户的抽象,可以处理很多事情,其中之一就是

代码基本上与@codegeek answer中的相同,但用户类上的“urole”属性应重命名为“roles”,并且角色必须是具有“name”属性的类(您可以从中复制粘贴)。您不需要定义login\u required,因为它已经实现为roles\u required。因此,我们没有使用
@login\u required(role='rolename')
而是使用
@roles\u required('rolename')


出于安全考虑,我刚开始使用这个API,这是一次很棒的体验。我强烈建议任何有密码、用户身份验证和用户角色问题的人。

简化您尝试的方法是使用角色,因为您使用的是Flask-SQLAlchemy,所以每个用户没有很多不同的类,并且使用的是继承。问题是我使用的现有数据库是独立的,并且有单独的数据。问题是我有一个现有数据库,其中有单独的学校和员工数据库,其中有数据。你认为这种方式仍然可行吗?我是否可以创建一个与数据库无关的通用用户类,而是包装一个学校或职员帐户?我不确定我是否完全理解您的意思,但通常情况下,您应该有一个通用用户类/模型,该类/模型通常对应于一个数据库表。我强烈建议您使用我上面解释的“角色”概念。它工作得很好。这是我采取的方法。非常感谢您提供了一个清晰、有用的答案。当蓝图位于不同的模块中时,您建议如何覆盖默认的
@login\u required
装饰器?1.导入答案中定义的自定义装饰器,或者以某种方式覆盖
flask\u login。需要登录的
?这不是答案,而是一个“用谷歌搜索这个”响应。这是可行的,但我需要从
is\u authenticated()
中删除
,因为它不是bool函数。如何覆盖标准的需要登录的装饰器?也就是说,如何让您的登录名代替标准的flask\u登录名来执行。login\u required?我很确定简单地定义它就会覆盖它。或者,如果您没有从flask_login显式导入login_required函数,则不需要覆盖login_。感谢您的回答,我有一个类似的问题,但我一直在为两个不同的用户类型使用两个类,问题是其中只有一个类应该与其他表有关系,那么我如何克服这个问题?谢谢你的帮助。
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