使用多用户 类 和 SSO 登录 Flask

Flask Login with Multiple User Classes and SSO

这里是 Flask 初学者。我的 flask-login 有三个用户 classes。 GoogleUser 和 FacebookUser 使用 SSO,不需要密码字段:

from InstaFlix import db, login_manager
from datetime import datetime
from flask_login import UserMixin

# Get a user by their ID
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(user_id)

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True) # primary keys are required by SQLAlchemy
    email = db.Column(db.String(100), unique =True, nullable=False)
    password = db.Column(db.String(60), nullable=False)
    name = db.Column(db.String(100), nullable=True)
    username = db.Column(db.String(20), unique=True, nullable=False)
    profile_pic = db.Column(db.String(100), unique=False, nullable=False, default='default.jpg')

class GoogleUser(db.Model, UserMixin):
    id = db.Column(db.String(20), primary_key=True) 
    email = db.Column(db.String(100), unique =True, nullable=False)
    name = db.Column(db.String(40), unique=True, nullable=False)
    profile_pic = db.Column(db.String(100), unique=False, nullable=True)

class FacebookUser(db.Model, UserMixin):
    id = db.Column(db.String(20), primary_key=True) 
    email = db.Column(db.String(100), unique =True, nullable=False)
    name = db.Column(db.String(40), unique=True, nullable=False)
    profile_pic = db.Column(db.String(100), unique=False, nullable=True)

我想加载特定的 class 取决于用户也走哪条路线。例如 https://127.0.0.1:5000/fb 将允许用户登录。然后调用 class FacebookUser 将其信息保存到。

但是,我一次只能return一个class。

如何根据路由使用 load_user() 函数调用特定用户 class?

截至目前,只能加载一个class,具体取决于我查询的是哪一个。

IMO,没有必要为不同的用户创建多个模型type/role,您可以创建一个新的列来存储用户类型。此外,您的 GoogleUserFacebookUser 模型中的列与 User 模型完全重复。我建议只为他们使用一个用户 class。更优雅更方便

如果你想区分不同的用户类型,只需像这样添加一个新列:

class User(db.Model, UserMixin):
    # ...
    login_type = db.Column(db.String(20))

如果确实需要使用多个用户模型,可以使用session来存储登录类型,例如:

from flask import session

@oauth_bp.route('/callback/<provider_name>')
def oauth_callback(provider_name):
    if provider_name not in providers.keys():
        abort(404)

    provider = providers[provider_name]
    response = provider.authorized_response()
    session['login_type'] = provider_name

然后在load_user中读取它,根据它的值使用不同的用户模型:

from flask import session

@login_manager.user_loader
def load_user(user_id):
    login_type = session.get('login_type')
    if login_type == 'google':
        return GoogleUser.get(user_id)
    elif login_type == 'facebook':
        return FacebookUser.get(user_id)
    else:
        return User.query.get(user_id)