我想使用我的应用程序迁移flask_dance,以便用户使用谷歌和其他社交网络进行授权。
我收到此错误:
return
在我建立蓝图和sqlalchemy后端之间的连接之前,应用程序运行正常,如果我删除Cannot get OAuth token without an associated user
行,则错误消失。
这是我的 __ init __。py :
google_blueprint.backend
这也是我的表格,我如何在 models.py :
中组织它们import os
from flask import Flask, redirect, url_for, current_app
from flask_login import current_user
from develop.models import (
db,
User,
OAuth
)
from flask_dance.contrib.google import make_google_blueprint
from flask_dance.consumer.backend.sqla import SQLAlchemyBackend
from flask_dance.consumer import oauth_authorized
from sqlalchemy.orm.exc import NoResultFound
def create_app(config_object):
app = Flask(__name__)
app.config.from_object(config_object)
db.init_app(app)
login_manager.init_app(app)
google_blueprint = make_google_blueprint(
client_id=app.config['GOOGLE_CLIENT_ID'],
client_secret=app.config['GOOGLE_CLIENT_SECRET'],
scope=["profile", "email"]
)
app.register_blueprint(google_blueprint, url_prefix='/login')
@oauth_authorized.connect_via(google_blueprint)
def google_logged_in(blueprint, token):
resp = blueprint.session.get("/oauth2/v2/userinfo")
if resp.ok:
account_info_json = resp.json()
email = account_info_json['email']
query = User.query.filter_by(email=email)
try:
user = query.one()
except NoResultFound:
user = User()
user.image = account_info_json['picture']
user.fullname = account_info_json['name']
user.username = account_info_json['given_name']
user.email = account_info_json['email']
db.session.add(user)
db.session.commit()
login_user(get_user, remember=True)
identity_changed.send(
current_app._get_current_object(),
identity=Identity(get_user.id)
)
@login_manager.user_loader
def load_user(userid):
return User.query.get(userid)
google_blueprint.backend = SQLAlchemyBackend(OAuth, db.session, user=current_user)
return app
请提供任何帮助:)
答案 0 :(得分:8)
TL; DR:您可以通过在SQLAlchemyStorage对象上设置user_required=False
来停用此例外。但是,由于某种原因引发异常,如果您只是像这样禁用它,您的数据库可能会进入意外状态,其中某些OAuth令牌未链接到用户。有一个更好的方法来解决这个问题。请继续阅读。
我是Flask-Dance的作者。此Cannot get OAuth token without an associated user
例外仅出现在Flask-Dance的0.13.0及更高版本中。 (CHANGELOG is here.)pull request introducing this change有更多关于更改原因的背景信息。
使用OAuth有几种不同的方法。以下是一些示例用例,所有这些都是Flask-Dance支持的:
用例1是最简单的:不要将user
或user_id
参数传递给SQLAlchemyStorage
,并假设您的应用程序不使用多个用户帐户。这意味着您的网站只能链接到远程服务上的一个特定帐户:只有一个Twitter帐户,只有一个Slack团队等。
用例2也很简单:将user
或user_id
参数传递给SQLAlchemyStorage
。 Flask-Dance会自动将OAuth令牌保存到您的数据库中,并将其链接到当前登录的用户。
用例3更复杂,因为它涉及同时自动创建OAuth令牌和本地用户帐户。不同的应用程序对创建用户帐户有不同的要求,Flask-Dance无法知道这些要求是什么。因此,Flask-Dance无法自动处理此用例。您必须挂钩oauth_authorized
信号,创建用户帐户并手动将其与OAuth令牌关联,然后返回False
告诉Flask-Dance不要尝试自动处理OAuth令牌。
在版本0.13.0之前,可能会在数据库中意外创建未与任何用户链接的OAuth令牌。在用例3中,OAuth令牌是在该用户的本地用户帐户之前创建的,因此Flask-Dance会将OAuth令牌保存到数据库而不包含任何链接的本地用户帐户。您可以使用oauth_authorized
处理程序将OAuth令牌与本地用户帐户关联,但如果您的代码有问题并引发异常,则OAuth令牌可能会保留在您的数据库中,永远与任何用户无关。
从版本0.13.0开始,Flask-Dance检测到此问题并引发异常,而不是在没有关联的本地用户帐户的情况下将OAuth令牌保存到数据库。有两种方法可以解决此问题:
SQLAlchemyStorage
对象上设置user_required=False
来停用此检查。我相信选项1是目前为止更好的解决方案,但它需要更多地了解Flask-Dance在幕后实际做的事情。 I've written some documentation that describes how to handle multi-user setups, which discusses this problem as well.