具有 Google 云端硬盘访问权限的 Flask Google 登录

标签 flask google-drive-api

我正在尝试创建一个 Flask 应用,该应用可以浏览到用户的 Google 云端硬盘以选择要转换为 CSV 格式的文件。

我在网上找到了添加 Google 登录的代码(见下文),但我不明白如何打印登录用户的所有文件。我发现我需要将 https://www.googleapis.com/auth/drive.file 添加到 scope 但我不明白如何列出所有文件来自 index 中的授权用户 (current_user.paying==True)。我知道可以使用以下代码来完成此操作,但我不确定如何定义凭据

回调中,已经生成了访问 token ,因此我尝试访问 Google Drive API 以仅搜索用户的 Google 表格:

from httplib2 import Http
from apiclient import discovery
from oauth2client import file

with open("./credentials.json", 'w') as outfile:
    json.dump(token_response.json(), outfile)

store = file.Storage("./credentials.json")
credentials = store.get()
drive = discovery.build("drive", "v3", http=credentials.authorize(Http()))
files = drive.files().list(q="mimeType='application/vnd.google-apps.spreadsheet'").execute()

但这给了我一个“KeyError: '_module'”错误,信息量不大。

这是使用 Google 登录的完整 Flask 代码

import os
import requests
import json
from httplib2 import Http
from apiclient import discovery
from oauthlib.oauth2 import WebApplicationClient

from flask import Flask, redirect, request, url_for
from flask_login import LoginManager, current_user, login_required, login_user, logout_user
from flask_login import UserMixin

authorized_users = ["myuser@gmail.com"]


class User(UserMixin):
    def __init__(self, id_, paying):
        self.id = id_
        self.paying = paying

    @staticmethod
    def get(user_email):

        if user_email not in authorized_users:
            user = User(user_email, False)
        else:
            user = User(user_email, True)
        return user



# Configuration
GOOGLE_CLIENT_ID = os.environ.get("GOOGLE_CLIENT_ID", None)
GOOGLE_CLIENT_SECRET = os.environ.get("GOOGLE_CLIENT_SECRET", None)
GOOGLE_DISCOVERY_URL = ("https://accounts.google.com/.well-known/openid-configuration")

# Flask app setup
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY") or os.urandom(24)

# User session management setup
login_manager = LoginManager()
login_manager.init_app(app)

# OAuth 2 client setup
client = WebApplicationClient(GOOGLE_CLIENT_ID)


# Flask-Login helper to retrieve a user from our db
@login_manager.user_loader
def load_user(user_email):
    return User.get(user_email)


def get_google_provider_cfg():
    return requests.get(GOOGLE_DISCOVERY_URL).json()


google_provider_cfg = get_google_provider_cfg()
token_endpoint = google_provider_cfg["token_endpoint"]

print("Google provider cfg", google_provider_cfg)

ACCESS_TOKEN_URI = 'https://www.googleapis.com/oauth2/v4/token'


@app.route("/")
def index():
    if current_user.is_authenticated:
        if current_user.paying:
            return f"<p>Hello, {current_user.id}! You're logged in!</p><br/><a class='button' href='/logout'>Logout</a>"
        else:
            return "Not authorized!<br/><a class='button' href='/logout'>Logout</a>"
    else:
        return f"<a class='button' href='/login'>Google Login</a>"


@app.route("/login")
def login():
    # Find out what URL to hit for Google login
    google_provider_cfg = get_google_provider_cfg()
    authorization_endpoint = google_provider_cfg["authorization_endpoint"]

    # Use library to construct the request for Google login and provide
    # scopes that let you retrieve user's profile from Google
    request_uri = client.prepare_request_uri(
        authorization_endpoint,
        redirect_uri=request.base_url + "/callback",
        scope=["openid", "email", "profile", "https://www.googleapis.com/auth/drive.file"],
    )
    return redirect(request_uri)


@app.route("/login/callback")
def callback():
    # Get authorization code Google sent back to you
    code = request.args.get("code")
    # Prepare and send a request to get tokens! Yay tokens!
    token_url, headers, body = client.prepare_token_request(
        token_endpoint,
        authorization_response=request.url,
        redirect_url=request.base_url,
        code=code
    )
    token_response = requests.post(
        token_url,
        headers=headers,
        data=body,
        auth=(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET),
    )

    # Parse the tokens!
    client.parse_request_body_response(json.dumps(token_response.json()))

    # Now that you have tokens (yay) let's find and hit the URL
    # from Google that gives you the user's profile information,
    # including their Google profile image and email
    userinfo_endpoint = google_provider_cfg["userinfo_endpoint"]
    uri, headers, body = client.add_token(userinfo_endpoint)
    userinfo_response = requests.get(uri, headers=headers, data=body)
    if userinfo_response.json().get("email_verified"):
        # unique_id = userinfo_response.json()["sub"]
        users_email = userinfo_response.json()["email"]
        picture = userinfo_response.json()["picture"]
        users_name = userinfo_response.json()["given_name"]
    else:
        return "User email not available or not verified by Google.", 400

    # Create a user in your db with the information provided
    # by Google
    user = User(users_email, False)
    #
    # # Doesn't exist? Add it to the database.
    # if not User.get(unique_id):
    # User.create(unique_id, users_name, users_email, picture)

    print("Logging", users_name, users_email, picture)

    # Begin user session by logging the user in
    login_user(user)

    # Send user back to homepage
    return redirect(url_for("index"))


@app.route("/logout")
@login_required
def logout():
    logout_user()
    print("Logging out")
    return redirect(url_for("index"))


if __name__ == "__main__":
    app.run(ssl_context="adhoc", debug=True)

最佳答案

获取凭据的简单方法是

  • 访问Google Drive API Quickstart
  • 点击启用驱动器
  • 记下客户端 ID客户端 key ,或者点击下载客户端配置并打开生成和下载的凭据。 json 文件

或者,您可以

更新

KeyError: '_module' 是由于检索结构不正确的 json 文件而产生的错误。

可能的原因:

  • 使用需要 client_secrets.json 的 API 客户端库文件 - 这与您从 Google Drive API 快速入门获取的 credentials.json 文件不同
  • json 文件中存储无效凭据
  • json 文件存储在 py 文件之外的另一个文件夹中
  • 使用无效范围

据我所知,您使用 WebApplicationClient并需要创建各自的client credentials for a Web Server .

json 文件 的内容应为

类型
{"web":{"client_id":"XXXX.apps.googleusercontent.com","project_id":"XXXX","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"XXX","redirect_uris":["https://script.google.com/oauthcallback"]}}

另外:

范围https://www.googleapis.com/auth/drive.file不足以列出用户驱动器上的所有文件 - 它只允许您访问使用您的应用程序创建/打开的文件。更多信息here

出于调试目的,我建议您将您的应用程序放在第一个慷慨的范围内。一旦解决了凭据问题并且您的应用程序可以正常运行 - 看看您可以在不影响应用程序功能的情况下限制范围到什么程度。

关于具有 Google 云端硬盘访问权限的 Flask Google 登录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60852287/

相关文章:

python - 如何在 AWS Elastic Beanstalk 上设置 HTTPS

android - 如何使用带有 react-native-drive-api-wrapper 的 react native 将图像上传到 google drive?

json - 有没有办法通过 redirector.googlevideo.com 获取指向谷歌驱动器视频文件的链接?

python - 无法从 models.py 导入类

python - Flask SQLAlchemy 分页错误

flask - Sqlalchemy - 加入后分组

python - 与 Flask 集成时 Ldap 模块失败

google-apps-script - 如何在谷歌电子表格中每行添加一个按钮?

android - 如何将我的 Android 应用程序连接到谷歌驱动器?

javascript - google drive api v3 创建文件夹无提示失败