如何无需重复认证通过GCP API读取Google Calendar日程用于仪表盘
解决方案
方法1:使用刷新令牌持久化授权(无需服务账号)
你现在的授权流程每次都走浏览器验证是因为没有持久化授权凭证,通过以下步骤可以实现长期免验证:
- 首次授权时自动获取长期有效的刷新令牌
- 将包含刷新令牌的凭证存储到本地文件
- 后续程序启动时直接读取本地凭证,
access_token过期时会自动用刷新令牌换取新的凭证,无需再次走浏览器授权流程
注意:如果你的GCP OAuth应用的发布状态为「测试」,刷新令牌默认7天过期,你需要在GCP控制台的「OAuth 同意屏幕」页面将应用发布状态改为「正式发布」,就可以获得长期有效的刷新令牌。
对应的Python代码示例:
import os.path 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 SCOPES = [ 'https://www.googleapis.com/auth/calendar.readonly', "openid", "https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile" ] client_config = { 'installed': { 'client_id': '123456.apps.googleusercontent.com', 'project_id': 'test-dashboard', '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': 'secret', 'redirect_uris': ['urn:ietf:wg:oauth:2.0:oob', 'http://localhost'] } } creds = None # 本地有存储的token文件就直接读取 if os.path.exists('token.json'): creds = Credentials.from_authorized_user_file('token.json', SCOPES) # 凭证不存在或者过期失效 if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: # 自动用刷新令牌换新的access token creds.refresh(Request()) else: # 首次运行走浏览器授权 flow = InstalledAppFlow.from_client_config(client_config, SCOPES) creds = flow.run_local_server() # 把新的凭证存到本地 with open('token.json', 'w') as token: token.write(creds.to_json()) service = build('calendar', 'v3', credentials=creds) # 后续业务逻辑不变 page_token = None cal = {} while True: calendar_list = service.calendarList().list(pageToken=page_token).execute() for calendar_list_entry in calendar_list['items']: cal[calendar_list_entry['summary']] = calendar_list_entry page_token = calendar_list.get('nextPageToken') if not page_token: break
方法2:服务账号读取个人Gmail日历方案
个人Gmail账号可以使用服务账号读取日历,你之前返回空结果是因为没有给服务账号授予日历的访问权限,无需使用全域委派,操作步骤如下:
- 在GCP控制台的服务账号页面复制服务账号的邮箱地址(格式类似
xxx@xxx.iam.gserviceaccount.com) - 打开Google日历网页端,找到你要读取的日历,点击「设置和共享」
- 在「与特定的人共享」选项下,点击「添加人员」,粘贴服务账号邮箱,权限选择「查看所有事件详情」,保存即可
对应的Python代码示例:
from google.oauth2 import service_account from googleapiclient.discovery import build SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'] SERVICE_ACCOUNT_FILE = '你的服务账号密钥文件路径.json' creds = service_account.Credentials.from_service_account_file( SERVICE_ACCOUNT_FILE, scopes=SCOPES) service = build('calendar', 'v3', credentials=creds) # 注意这里要指定你共享给服务账号的日历ID,不要用primary,个人账号的primary日历不会自动出现在calendarList里 calendar_id = "你的个人Gmail地址,或者日历设置里的日历ID" events = service.events().list(calendarId=calendar_id).execute()
关于全域委派的说明
你的理解正确,全域委派仅适用于Google Workspace企业账号,只能访问所属企业域名下的用户资源,个人Gmail账号没有对应的企业域名,无法使用全域委派功能访问个人日历。
内容的提问来源于stack exchange,提问作者viertel97
相关产品推荐
相关产品推荐

