Flask_dance:如果没有关联用户,则无法获取 OAuth 令牌

2024-05-01

我想将 Flask_dance 与我的应用程序一起迁移,以使用户授权使用谷歌和其他社交网络。

我收到此错误:

Cannot get OAuth token without an associated user

在我在蓝图和 sqlalchemy 后端之间建立连接之前,如果我删除了google_blueprint.backend行错误消失。

这是我的__init__.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

这也是我的表格,我是如何组织它们的模型.py:

class User(db.Model, UserMixin):
    id = db.Column(db.Integer(), primary_key=True)
    image = db.Column(db.String(), nullable=True)
    fullname = db.Column(db.String())
    username = db.Column(db.String(), unique=True)
    password = db.Column(db.String())
    email = db.Column(db.String(), unique=True)

class OAuth(OAuthConsumerMixin, db.Model):
    user_id = db.Column(db.Integer(), db.ForeignKey(User.id))
    user = db.relationship(User)

请提供任何帮助,我们将不胜感激:)


TL;DR:您可以通过设置禁用此异常user_required=False on the SQLAlchemy 存储 https://flask-dance.readthedocs.io/en/latest/api.html#flask_dance.consumer.storage.sqla.SQLAlchemyStorage目的。但是,引发异常是有原因的,如果您只是像这样禁用它,您的数据库可能会进入意外状态,其中某些 OAuth 令牌未链接到用户。有一个更好的方法来解决这个问题。请继续阅读以了解详细信息。


我是作者烧瓶舞 https://flask-dance.readthedocs.io. This Cannot get OAuth token without an associated user异常仅存在于 Flask-Dance 0.13.0 及更高版本中。 (变更日志在这里。 https://github.com/singingwolfboy/flask-dance/blob/master/CHANGELOG.rst#0130-2017-11-12) The 引入此更改的拉取请求 https://github.com/singingwolfboy/flask-dance/pull/92有更多关于为何进行更改的背景信息。

使用 OAuth 的方式有多种。以下是一些示例用例,所有 Flask-Dance 都支持:

  1. 我想构建一个可以连接到一项特定服务的机器人,例如向特定帐户发送推文的 Twitter 机器人,或者连接到特定 Slack 团队的 Slack 机器人。我希望这个机器人能够响应 HTTP 请求,因此它必须作为网站运行,尽管我不希望人们实际上use直接这个网站。
  2. 我想建立一个用户可以登录的网站。用户需要使用用户名和密码在我的网站上创建一个帐户。After他们已经创建了一个帐户,用户可以决定将其帐户链接到其他 OAuth 提供商(例如 Google 或 Facebook),以解锁其他功能。
  3. 我想建立一个用户可以登录的网站。用户应该能够通过使用 GitHub(或任何其他 OAuth 提供商)登录来创建自己的帐户。用户不需要为我的网站创建新密码。

用例 1 是最简单的:不传递user or user_id论证你的SQLAlchemyStorage,并且它会假设您的应用程序不使用多个用户帐户。这意味着您的网站只能链接到远程服务上的一个特定帐户:只有一个 Twitter 帐户、只有一个 Slack 团队等。

用例 2 也非常简单:传递 auser or 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 令牌保存到数据库中。有两种方法可以解决这个问题:

  1. 重写代码以手动创建用户帐户并将其与 OAuth 令牌关联。该文档包含一些可用于此目的的示例代码。 https://flask-dance.readthedocs.io/en/latest/quickstart.html#sqlalchemy
  2. 禁用此检查,并告诉 Flask-Dance 可以在没有关联用户的情况下创建 OAuth 令牌。您可以通过设置禁用此检查user_required=False on the SQLAlchemyStorage https://flask-dance.readthedocs.io/en/latest/api.html#flask_dance.consumer.storage.sqla.SQLAlchemyStorage object.

我相信选项 1 是迄今为止更好的解决方案,但它需要更多地了解 Flask-Dance 在幕后实际所做的事情。我写了一些文档来描述如何处理多用户设置,其中也讨论了这个问题。 https://flask-dance.readthedocs.io/en/latest/multi-user.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Flask_dance:如果没有关联用户,则无法获取 OAuth 令牌 的相关文章

  • Flask 无法播放 html 中的视频

    我有一个 Flask 应用程序 应该在加载页面时播放视频 但它只显示在左上角 并且不会从视频的第一帧开始改变 我已经尝试将其插入 html 代码但它不起作用 extends base html block content
  • 在 FlaskForm (WTForms) 中传递并使用变量

    该代码非常不言自明 我想将一个变量传递给FlaskForm子类以供进一步使用 from flask import Flask render template string from flask wtf import FlaskForm fr
  • Python 中的 Flask 错误:“无法导入 webapp”

    我正在尝试运行 Flask 但是 每当我输入 flask run 时 都会出现错误 Could not import webapp 作为参考 我正在使用 Visual Studio Code 并运行以下代码 from flask impor
  • Flask Restful 解析器列表字典

    我有一个解析请求列表字典的示例 shopping cart id 23323 qty 10 id 34232 qty 9 id 34232 qty 9 我如何使用flask restful RequestParser解析它 使用这样的东西
  • login_required 装饰器不起作用,flask-Login 允许匿名用户

    我装饰了一个方法login required 但令我惊讶的是它不是执行完全允许匿名用户进入 打印current user方法内返回
  • Flask-SocketIO 未使用 Gevent/Gevent-websocket

    我正在使用 Flask 和 Flask SocketIO 构建用于 websocket 通信的 Web 界面 数据 API 我想开始转向使用 Gevent Gevent websocket Gunicorn 以及最终使用 Nginx 进行负
  • 将 matplotlib png 转换为 base64 以在 html 模板中查看

    背景 你好 我正在尝试制作一个简单的网络应用程序 按照教程计算阻尼振动方程 并将结果的 png 返回到 html 页面 然后将其转换为 Base64 字符串 Problem 该应用程序运行正常 只是在计算结果时返回损坏的图像图标 可能是因为
  • 在 jinja2 模板中转义 jinja2 语法

    我在 Flask 中提供来自 Jinja2 模板的动态页面 现在 我在脚本标记内定义客户端模板 比如 Jinja2 clone Nunjucks 问题是 客户端模板的语法如下 that Flask sJinja2 解释器可以解释而不是渲染v
  • 在 Flask 中使用 html 运行 python 脚本

    我是 Flask 新手 我试图在单击 html 页面中的按钮时从后台运行 python 脚本 这是我的代码 from flask import from functools import wraps import sqlite3 app F
  • 烧瓶 - 404 未找到

    我是烧瓶开发的新手 这是我在烧瓶中的第一个程序 但它向我显示了这个错误 在服务器上找不到请求的 URL 如果您输入了网址 请手动检查拼写并重试 这是我的代码 from flask import Flask app Flask name ap
  • 操作错误:尝试在 ubuntu 服务器中写入只读数据库

    我正在使用 FlaskApp 运行mod wsgi and apache2在 Ubuntu 服务器上 我尝试运行烧瓶应用程序localhost成功 然后部署到ubuntu服务器上 但是当我尝试更新数据库时 出现错误 Failed to up
  • Flask 应用程序路由中的多个参数

    烧瓶怎么写app route如果我在 URL 调用中有多个参数 这是我从 AJax 调用的 URL http 0 0 0 0 8888 createcm summary VVV change Feauure 我试图写我的烧瓶app rout
  • 如何在连接到 Heroku PostgreSQL 的 Flask 应用程序上处理更多并发用户?

    Heroku 上的 Flask API 有许多端点 它们在将 json 化结果返回给客户端之前在我的 Heroku PostgreSQL 数据库上运行查询 我当前的计划是 Hobby Basic 层 因此数据库最多只能处理 20 个连接 如
  • Alembic:如何迁移模型中的自定义类型?

    My User模型是 class User UserMixin db Model tablename users noinspection PyShadowingBuiltins uuid Column uuid GUID default
  • 使用python将json和文件发送到flask

    我遇到这个问题 我试图在单个函数中向 Flask API 发送 接收一些文件和 JSON 在我的客户端 发件人 上我有 my json to be sent datas var1 var1 var2 var2 my file to be s
  • 删除flask中的一对一关系

    我目前正在使用 Flask 开发一个应用程序 并且在删除一对一关系中的项目时遇到了一个大问题 我的模型中有以下结构 class User db Model tablename user user id db Column db String
  • 无法让gunicorn使用Python 3

    我有 Ubuntu NGINX Gunicorn 以及可与 Python 3 设置配合使用的虚拟环境 但我的 Flask 应用程序仍然以 2 7 6 运行 我已系统地按照说明进行操作 但找不到解决方案 Gunicorn 配置文件 progr
  • Docker Flask ModuleNotFoundError:没有名为“flask”的模块

    我在执行时遇到以下错误 docker compose up build web 1 Traceback most recent call last web 1 File glm plotter py line 4 in
  • 使用所有连接的 Flask unittest 和 sqlalchemy

    在进行了大约 100 个单元测试后 我刚刚在 Flask 应用程序上运行单元测试时遇到了问题 所有单元测试都会通过 但是当一次全部运行时 它们将失败并出现以下错误 OperationalError OperationalError FATA
  • SocketIO + Flask 检测断开连接

    我在这里有一个不同的问题 但意识到它可以简化为 如何检测客户端何时从页面断开连接 关闭其页面或单击链接 换句话说 套接字连接关闭 我想制作一个带有更新用户列表的聊天应用程序 并且我在 Python 上使用 Flask 当用户连接时 浏览器发

随机推荐