Django+React集成Google OAuth2时csrftoken失效致/me接口鉴权失败
Django+React跨域OAuth登录后/me接口返回匿名用户问题排查修复
问题根因
跨域场景下身份凭证未正常传递、前后端配置存在冲突,导致SessionAuthentication无法识别已登录用户。手动传CSRF token无法完成鉴权,Session鉴权核心依赖的sessionidCookie未被前端携带、后端Cookie配置错误导致浏览器不存储凭证,是问题的核心诱因。
修复步骤
1. 修复前端Axios配置
当前配置withCredentials: false是直接问题点:跨域请求默认不会携带Cookie类身份凭证,必须开启该配置才会自动附带上sessionid和csrftoken,和curl请求手动带Cookie才能鉴权成功的逻辑一致。
另外现有getCookie函数逻辑错误、存在大量冗余硬编码的无效请求头,替换为以下代码:
// 全局axios配置 axios.defaults.withCredentials = true; axios.defaults.xsrfHeaderName = "X-CSRFToken"; axios.defaults.xsrfCookieName = "csrftoken"; // 修复Cookie读取逻辑 function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } // 调用/me接口,删除所有硬编码的无效头和参数 axios({ method: 'get', url: 'http://localhost:8000/registration/me/', }).then(res => { console.log("用户信息获取成功:", res.data); }).catch(err => { console.error("请求失败:", err.message); });
2. 清理Django侧冲突的CORS/CSRF配置
现有配置存在重复赋值、环境不匹配的问题,替换为以下配置:
# CORS配置 CORS_ALLOWED_ORIGINS = ["http://localhost:3000"] CORS_ALLOW_CREDENTIALS = True CORS_EXPOSE_HEADERS = ["Content-Type", "X-CSRFToken"] # 本地开发可保留,生产环境建议关闭并指定允许的源 ALLOWED_HOSTS = ['*'] # CSRF与Session配置 CSRF_COOKIE_NAME = "csrftoken" # 本地HTTP开发必须设为False,否则浏览器不会存储Cookie CSRF_COOKIE_SECURE = False SESSION_COOKIE_SECURE = False CSRF_COOKIE_HTTPONLY = False CSRF_COOKIE_DOMAIN = 'localhost' # 关闭SameSite限制,避免本地跨域场景Cookie被拦截 SESSION_COOKIE_SAMESITE = None CSRF_COOKIE_SAMESITE = None # 将前端源加入CSRF信任列表 CSRF_TRUSTED_ORIGINS = ["http://localhost:3000"] # 先关闭该配置,避免CSRF Token存在Session中导致前端无法读取 CSRF_USE_SESSIONS = False
注意:原配置中
CSRF_COOKIE_SECURE = True仅适用于HTTPS环境,本地HTTP开发开启后浏览器会直接拒绝下发和存储Cookie,直接导致鉴权失效。
3. 修复DRF接口权限配置
在函数体内写permission_classes = [IsAuthenticated]不会生效,必须通过装饰器挂载权限类,否则接口会放行匿名请求:
from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response @api_view(['GET']) @permission_classes([IsAuthenticated]) def current_user(request): user = request.user return Response({ 'username' : user.username, 'email' : user.email, 'firstname' : user.first_name, 'lastname' : user.last_name, 'picture' : getattr(user, 'picture', ''), 'email_verified' : getattr(user, 'email_verified', False), 'locale' : getattr(user, 'locale', ''), })
验证方式
- 清除浏览器localhost域名下所有存量Cookie,重新走Google OAuth登录流程
- 登录跳转回前端后,打开开发者工具Application面板,确认8000端口域名下存在
sessionid和csrftoken两个Cookie - 发起/me请求时,查看请求头确认自动携带了包含两个凭证的Cookie字段、以及X-CSRFToken请求头
- 此时接口将正常返回已登录用户信息,不再返回匿名用户标识
内容的提问来源于stack exchange,提问作者london_utku
相关产品推荐
相关产品推荐

