跨域场景下Django登录请求CSRF验证403问题求助
解决跨域Django allauth登录的CSRF 403问题
核心问题分析
你的场景是跨域(A.com前端 → B.com后端)提交登录表单,当前方案的关键问题在于:
- 手动设置
document.cookie时未指定domain为B.com,导致cookie被存在A.com域下,提交表单到B.com时不会携带该cookie /getToken接口没有利用Django原生的CSRF cookie设置逻辑,且AJAX请求未开启跨域凭证支持,浏览器无法跨域保存B.com的CSRF cookie- Django的CSRF验证要求请求中携带的token与B.com域下的csrftoken cookie完全匹配,两者缺一则会触发403错误
具体修复步骤
1. 修正后端/getToken接口逻辑
不需要手动返回token,直接让Django通过响应头自动设置CSRF cookie:
from django.middleware.csrf import get_token from django.http import JsonResponse def getToken(request): # 调用get_token会自动在响应头设置Set-Cookie: csrftoken=xxx get_token(request) # 可选返回token,方便前端填充表单,核心是让浏览器接收Set-Cookie return JsonResponse({'token': request.META.get('CSRF_COOKIE')})
2. 前端AJAX请求开启跨域凭证
修改$.ajax配置,添加跨域凭证支持,确保浏览器保存B.com的CSRF cookie:
window.onload = function(){ $.ajax({ url: "https://B.com/getToken", type: 'GET', dataType: 'json', xhrFields: { withCredentials: true // 关键:允许跨域携带/保存凭证 }, success: function(res) { console.log(res); // 从cookie中读取csrftoken,比依赖接口返回值更可靠 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; } $('#csrf').val(getCookie('csrftoken')); } }) };
3. 完善Django配置
在settings.py中补充CSRF cookie的跨域配置:
class Config(ConfigMixin): # 保留原有配置 CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_WHITELIST = ('https://A.com',) CSRF_TRUSTED_ORIGINS = values.ListValue(environ=True, default=['https://A.com']) # 新增配置:绑定CSRF cookie到后端域名 CSRF_COOKIE_DOMAIN = 'B.com' # HTTPS环境下强制cookie使用secure属性 CSRF_COOKIE_SECURE = True # 允许跨域访问cookie(None需配合Secure,Lax兼容多数场景) CSRF_COOKIE_SAMESITE = 'Lax' @staticmethod def before_binding(configuration: ComposedConfiguration) -> None: configuration.REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] += [ 'rest_framework.authentication.TokenAuthentication' ]
4. 验证请求信息
提交表单前,打开浏览器开发者工具(Network面板),检查:
- 请求头中是否携带
Cookie: csrftoken=xxx(来自B.com域) - Form Data中
csrfmiddlewaretoken的值是否与cookie中的一致
额外说明
- 普通表单跨域提交时,浏览器会自动携带目标域(B.com)的cookie,前提是cookie的
domain和samesite配置正确 - 无需手动设置
document.cookie,依赖Django的Set-Cookie响应头让浏览器自动管理cookie是更可靠的方式
内容的提问来源于stack exchange,提问作者MMzztx
相关产品推荐
相关产品推荐

