我目前正在为我的大学建立一个名为 EduInsights 的网站来管理学期成绩。我想要访问 Google 提供的驱动器和工作表 API,以将结果导出到电子表格,并从驱动器文件夹中的 PDF 中提取结果。在 GCP 控制台中,我创建了凭据并将其下载为 .json 文件。当我第一次授权我的应用程序并在 token.json 文件中生成令牌时,几天后令牌就会过期,我必须删除该文件并重新授权。
我想要一个解决方案,一旦我授权并获得令牌,我不希望它过期。特别是因为我已经对应用程序进行了 docker 化,并且我不希望从 docker 到我的用户重定向到授权链接的复杂性,因为应用程序将使用同一个 google 帐户作为 API。我已经提供了用于身份验证的
authenticate.py
文件的代码。
import os
from dotenv import load_dotenv
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# Get the absolute path to the directory containing this Python script (alembic folder)
current_dir = os.path.dirname(os.path.abspath(__file__))
print(f"Current directory: {current_dir}", flush=True)
# Get the absolute path to the project root directory (two levels up from the current directory)
project_root = os.path.abspath(os.path.join(current_dir, ".", ".."))
print(f"Project root directory: {project_root}", flush=True)
# Load environment variables from the .env file located in the project root directory
dotenv_path = os.path.join(project_root, ".env")
print(f"Loading environment variables from: {dotenv_path}", flush=True)
load_dotenv(dotenv_path)
# defining credentials file path from environment variable
credentials_file_path = os.getenv("GOOGLE_API_CREDENTIALS")
# defining scopes for drive and sheets API
SCOPES = [
"https://www.googleapis.com/auth/spreadsheets",
"https://www.googleapis.com/auth/drive",
]
# authenticate drive API
def driveAPI(SCOPES):
"""
Authenticate with Google Drive API.
Parameters:
SCOPES (list): A list of OAuth 2.0 scopes defining the level of access to Google Drive resources.
Returns:
Resource: An authenticated Google Drive service object.
Raises:
HttpError: An error occurred while attempting to authenticate or build the service.
"""
credentials = None
# Check if token file exists
if os.path.exists("token.json"):
credentials = Credentials.from_authorized_user_file("token.json", scopes=SCOPES)
# If credentials are not valid or do not exist, perform authentication
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
# Refresh the expired credentials
credentials.refresh(Request())
else:
# Perform OAuth 2.0 authentication
flow = InstalledAppFlow.from_client_secrets_file(
credentials_file_path, SCOPES
)
credentials = flow.run_local_server(port=0)
# Save the refreshed or newly acquired credentials to token file
with open("token.json", "w") as token:
token.write(credentials.to_json())
try:
# Build the Google Drive service
drive_service = build("drive", "v3", credentials=credentials)
return drive_service
except HttpError as error:
# Handle any HTTP errors
print(error)
# Authenticate sheets API
def sheetsAPI(SCOPES):
"""
Authenticate with Google Sheets API.
Parameters:
SCOPES (list): A list of OAuth 2.0 scopes defining the level of access to Google Sheets resources.
Returns:
Resource: An authenticated Google Sheets service object.
Raises:
HttpError: An error occurred while attempting to authenticate or build the service.
"""
credentials = None
# Check if token file exists
if os.path.exists("token.json"):
credentials = Credentials.from_authorized_user_file("token.json", scopes=SCOPES)
# If credentials are not valid or do not exist, perform authentication
if not credentials or not credentials.valid:
if credentials and credentials.expired and credentials.refresh_token:
# Refresh the expired credentials
credentials.refresh(Request())
else:
# Perform OAuth 2.0 authentication
flow = InstalledAppFlow.from_client_secrets_file(
credentials_file_path, SCOPES
)
credentials = flow.run_local_server(port=0)
# Save the refreshed or newly acquired credentials to token file
with open("token.json", "w") as token:
token.write(credentials.to_json())
try:
# Build the Google Sheets service
sheets_service = build("sheets", "v4", credentials=credentials)
return sheets_service
except HttpError as error:
# Handle any HTTP errors
print(error)
我已经尝试了上面的代码,并在 GCP 控制台中寻找更改过期时间的选项,但我从未找到它。
我发现了另一个问题,但对于这个问题我自己心里有答案:https://stackoverflow.com/a/13851781