使用Django+React对接Google Auth时遇redirect_uri_mismatch错误求助
解决Django对接Google OAuth的redirect_uri_mismatch错误
核心问题:重定向URI不匹配
Error 400: redirect_uri_mismatch 本质是代码中设置的
REDIRECT_URI和Google Cloud控制台里配置的重定向URI不完全一致,Google OAuth要求两者必须精确匹配——包括协议(http/https)、域名、端口、路径,甚至末尾的斜杠都不能有差异。
排查步骤:
- 对比代码中的
REDIRECT_URI(http://localhost:3000/parent/our_information)和控制台配置的URL,重点检查:- 协议:控制台是否写的是
http(本地开发无需用https) - 端口:是否为
3000而非其他端口 - 路径:
/parent/our_information是否完全一致,有无多写/少写斜杠、大小写错误 - 确认控制台修改后已保存,部分场景下配置生效需等待1-2分钟
- 协议:控制台是否写的是
代码优化建议(针对Django新手)
1. 配置项统一移到settings.py
把硬编码的配置放到项目settings.py中,方便后续维护:
# settings.py import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent GOOGLE_CLIENT_SECRET_FILE = os.path.join(BASE_DIR, 'your_app_name/client_secret.json') GOOGLE_SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'] GOOGLE_REDIRECT_URI = 'http://localhost:3000/parent/our_information'
视图中导入使用:
from django.conf import settings # 替换原硬编码常量 CLIENT_SECRET_FILE = settings.GOOGLE_CLIENT_SECRET_FILE SCOPES = settings.GOOGLE_SCOPES REDIRECT_URI = settings.GOOGLE_REDIRECT_URI
2. 将ExchangeCodeView改为POST请求
用GET传递授权码code存在安全风险,改为POST更符合OAuth最佳实践:
from rest_framework import status from rest_framework.response import Response class ExchangeCodeView(APIView): def post(self, request): code = request.data.get('code') if not code: return Response({'error': '授权码code不能为空'}, status=status.HTTP_400_BAD_REQUEST) flow = Flow.from_client_secrets_file( CLIENT_SECRET_FILE, scopes=SCOPES, redirect_uri=REDIRECT_URI ) try: flow.fetch_token(code=code) except Exception as e: return Response({'error': f'兑换授权码失败:{str(e)}'}, status=status.HTTP_400_BAD_REQUEST) credentials = flow.credentials return Response({ 'access_token': credentials.token, 'refresh_token': credentials.refresh_token })
前端对应修改:
const handleCallback = () => { const urlParams = new URLSearchParams(window.location.search); const code = urlParams.get('code'); axios.post('http://localhost:8000/email/exchangeToken/', { code }) .then((response) => { const { access_token, refresh_token } = response.data; console.log('Access Token:', access_token); console.log('Refresh Token:', refresh_token); }) .catch((error) => { console.error(error); }); };
3. 配置CORS解决跨域问题
前端(3000端口)和Django(8000端口)属于不同域,需配置跨域允许:
- 安装依赖:
pip install django-cors-headers - 在settings.py中添加配置:
INSTALLED_APPS = [ # ...其他已安装应用 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', # 需放在CommonMiddleware之前 'django.middleware.common.CommonMiddleware', # ...其他中间件 ] # 允许本地前端访问 CORS_ALLOWED_ORIGINS = [ "http://localhost:3000", ]
4. 确保获取refresh_token
默认情况下Google不会返回refresh_token,需在生成授权URL时添加access_type='offline'参数:
auth_url, _ = flow.authorization_url( prompt='consent', access_type='offline' # 强制返回refresh_token )
额外注意事项
- 确保Google Cloud中创建的是Web应用类型的OAuth客户端ID,而非桌面/移动端类型
- 本地开发时不要混用
localhost和127.0.0.1,代码和控制台配置保持一致
内容的提问来源于stack exchange,提问作者TINTIN
相关产品推荐
相关产品推荐

