React+Django项目Google登录遇400 Bad Request错误求助
Django REST + React Google登录400错误解决方案
核心问题
你后端用id_token.verify_oauth2_token验证的是Google ID Token,但前端传递的是access_token——这两个令牌用途完全不同,Google的验证方法只认ID Token,直接验证access_token会触发ValueError,导致返回400错误。
修复步骤
1. 前端修改:传递ID Token而非access_token
在useGoogleLogin中指定返回ID Token,并将其发送给后端:
const gLogin = useGoogleLogin({ responseType: 'id_token', // 要求Google返回ID Token onSuccess: tokenResponse => { axios.post('http://127.0.0.1:8000/api/auth/google/signin/', { token: tokenResponse.id_token // 传递id_token而非access_token }) .then(response => { console.log('Successfully logged in'); }) .catch(error => { console.error('failed to login'); }) }, });
2. 后端代码优化
除了令牌类型问题,优化代码规范和异常处理:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from django.contrib.auth import authenticate, login from google.oauth2 import id_token from google.auth.transport import requests from django.conf import settings class GoogleSignInView(APIView): def post(self, request): token = request.data.get('token') if not token: return Response({'error': 'Token is missing.'}, status=status.HTTP_400_BAD_REQUEST) try: # 验证ID Token的有效性 idinfo = id_token.verify_oauth2_token( token, requests.Request(), settings.GOOGLE_CLIENT_ID ) # 校验令牌签发方,防止伪造 if idinfo['iss'] not in ['accounts.google.com', 'https://accounts.google.com']: raise ValueError('Invalid token issuer.') email = idinfo.get('email') # 确保用户邮箱已验证 if not email or not idinfo.get('email_verified'): return Response({'error': 'Email not verified or missing.'}, status=status.HTTP_400_BAD_REQUEST) # 验证系统内用户 user = authenticate(request, email=email) if user: login(request, user) return Response({'success': True}) else: return Response({'error': 'User does not exist.'}, status=status.HTTP_404_NOT_FOUND) except ValueError as e: # 令牌无效、过期、签名错误等都会触发此异常 return Response({'error': f'Invalid token: {str(e)}'}, status=status.HTTP_400_BAD_REQUEST) except Exception as e: return Response({'error': f'Server error: {str(e)}'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
3. 必要检查项
- Google Cloud配置:确保OAuth 2.0客户端已添加正确的授权JavaScript来源(如
http://localhost:3000),避免令牌被Google判定为非法来源。 - Django认证后端:若用邮箱作为登录标识,需在
settings.py配置支持邮箱登录的认证后端:AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', # 自定义后端示例(需自行实现) 'your_app.backends.EmailAuthenticationBackend', ] - CORS设置:用
django-cors-headers库允许前端域名访问后端API,settings.py配置示例:INSTALLED_APPS = ['corsheaders'] MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware'] CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]
额外说明
Google的access_token用于调用Google开放API(如通讯录、日历),而ID Token专用于身份验证——登录场景下使用ID Token是OpenID Connect的标准流程,不要混淆两者的用途。
内容的提问来源于stack exchange,提问作者Nandan
相关产品推荐
相关产品推荐

