使用OAuth2.0授权后Google Calendar API v3报错求助
Django集成Google Calendar API授权失败的解决办法
问题根源
- 用错了工具类:
InstalledAppFlow是给桌面应用设计的,Django作为Web应用,得用google_auth_oauthlib.flow.Flow才行 - 手动拼接
redirect_uri的方式错误,应该在初始化Flow时直接指定,且必须和Google Cloud控制台里的配置完全一致 - 端口号出现笔误:代码里写的是43759,但实际跳转的是47759,导致地址无法访问
- 缺少回调视图:Google授权完成后需要跳回你的Django应用,必须有对应的路由和视图处理这个回调请求
一步步修复
1. 替换为Web专用的Flow生成授权URL
废弃InstalledAppFlow,改用Web应用适配的Flow类,正确指定重定向URI:
from google_auth_oauthlib.flow import Flow from django.conf import settings SCOPES = ['https://www.googleapis.com/auth/calendar'] def get_google_auth_url(request): # 从settings读取配置,避免硬编码路径 flow = Flow.from_client_secrets_file( settings.GOOGLE_CLIENT_SECRET_PATH, scopes=SCOPES, # 直接指定重定向URI,比如开发环境的回调地址 redirect_uri=settings.GOOGLE_REDIRECT_URI ) # 加access_type='offline'才能获取刷新令牌,避免令牌过期后重复授权 auth_url, state = flow.authorization_url( access_type='offline', include_granted_scopes='true' ) # 把state存入session,回调时验证防止恶意请求 request.session['oauth_state'] = state return auth_url
2. 同步Google Cloud控制台的重定向URI
- 登录Google Cloud控制台,进入你的项目 → 「API和服务」→「凭据」
- 找到你的OAuth 2.0客户端ID,编辑其重定向URI,确保和Django中
GOOGLE_REDIRECT_URI完全一致,比如http://localhost:43759/calendar/oauth-callback/ - 重点:端口号必须和Django实际运行的端口一致,修正43759/47759的笔误
3. 编写Django回调视图和路由
回调视图(示例存于app的views.py):
from google_auth_oauthlib.flow import Flow from django.conf import settings from django.http import HttpResponseRedirect from django.shortcuts import render def google_oauth_callback(request): # 验证state,防止CSRF攻击 session_state = request.session.get('oauth_state') request_state = request.GET.get('state') if not session_state or session_state != request_state: return render(request, 'error.html', {'msg': '授权状态验证失败'}) # 初始化Flow,复用之前存储的state和指定的重定向URI flow = Flow.from_client_secrets_file( settings.GOOGLE_CLIENT_SECRET_PATH, scopes=SCOPES, state=session_state, redirect_uri=settings.GOOGLE_REDIRECT_URI ) # 用授权码交换访问令牌与刷新令牌 flow.fetch_token(authorization_response=request.build_absolute_uri()) # 拿到API调用凭证,可存入session或数据库供后续使用 credentials = flow.credentials request.session['google_calendar_credentials'] = { 'token': credentials.token, 'refresh_token': credentials.refresh_token, 'token_uri': credentials.token_uri, 'client_id': credentials.client_id, 'client_secret': credentials.client_secret, 'scopes': credentials.scopes } # 授权成功后跳转至业务页面 return HttpResponseRedirect('/calendar/dashboard/')
路由配置(app的urls.py):
from django.urls import path from . import views urlpatterns = [ # 生成授权URL的接口,前端可请求此接口获取auth_url path('calendar/get-auth-url/', views.get_google_auth_url, name='get_google_auth'), # 回调地址,必须与Google Cloud配置的重定向URI完全匹配 path('calendar/oauth-callback/', views.google_oauth_callback, name='google_oauth_callback'), ]
4. 统一端口号
检查Django启动端口,确保GOOGLE_REDIRECT_URI、Google Cloud控制台配置的重定向URI、Django实际运行端口三者完全一致,彻底解决端口笔误问题。
额外提醒
- 开发环境下,Django的
ALLOWED_HOSTS需添加localhost和127.0.0.1,避免跨域或访问报错 - 客户端密钥文件不要提交到代码仓库,建议通过环境变量或settings.py配置读取
- 必须保留
access_type='offline'参数,否则令牌过期后用户需要重新授权,影响使用体验
内容的提问来源于stack exchange,提问作者Germano
相关产品推荐
相关产品推荐

