You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

跨域场景下Django登录请求CSRF验证403问题求助

解决跨域Django allauth登录的CSRF 403问题

核心问题分析

你的场景是跨域(A.com前端 → B.com后端)提交登录表单,当前方案的关键问题在于:

  1. 手动设置document.cookie时未指定domain为B.com,导致cookie被存在A.com域下,提交表单到B.com时不会携带该cookie
  2. /getToken接口没有利用Django原生的CSRF cookie设置逻辑,且AJAX请求未开启跨域凭证支持,浏览器无法跨域保存B.com的CSRF cookie
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 19:20:36