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

如何将Django登录页迁移至外部服务器(解决CSRF令牌缺失问题)

解决外部服务器表单提交Django登录的CSRF问题

针对跨域提交登录表单触发CSRF令牌缺失的问题,有以下几种可行方案:

方案一:主动获取Django的CSRF令牌并填充表单

Django的CSRF令牌会同时存在于登录页面的隐藏字段和响应Cookie中,外部页面可以通过JS先请求登录页面获取令牌,再添加到表单里提交:

  1. 配置Django允许跨域:
    在settings.py中添加外部服务器域名到信任列表:

    CSRF_TRUSTED_ORIGINS = ['https://your-external-server.com'] # 替换为你的外部服务器域名
    CORS_ALLOWED_ORIGINS = ['https://your-external-server.com']
    

    (需先安装django-cors-headers:pip install django-cors-headers,并将corsheaders加入INSTALLED_APPS,添加corsheaders.middleware.CorsMiddleware到中间件列表)

  2. 外部页面添加JS逻辑获取并填充令牌:

    // 页面加载时获取CSRF令牌
    window.addEventListener('load', function() {
      fetch('http://djangoserver.com/accounts/login/', {
        credentials: 'include' // 必须携带Cookie才能拿到csrftoken
      })
      .then(() => {
        // 从Cookie提取csrftoken
        const csrfToken = document.cookie.split('; ')
          .find(row => row.startsWith('csrftoken='))?.split('=')[1];
        if (csrfToken) {
          // 给表单添加隐藏的CSRF令牌字段
          const form = document.querySelector('form');
          const csrfInput = document.createElement('input');
          csrfInput.type = 'hidden';
          csrfInput.name = 'csrfmiddlewaretoken';
          csrfInput.value = csrfToken;
          form.appendChild(csrfInput);
        }
      })
      .catch(err => console.log('获取CSRF令牌失败:', err));
    });
    

方案二:给Django登录视图禁用CSRF校验(不推荐)

如果完全信任外部服务器,可以跳过该视图的CSRF校验,直接接收跨域表单提交:

  1. 自定义登录视图:

    from django.contrib.auth.views import LoginView
    from django.views.decorators.csrf import csrf_exempt
    from django.utils.decorators import method_decorator
    
    @method_decorator(csrf_exempt, name='dispatch')
    class NoCsrfLoginView(LoginView):
        template_name = 'registration/login.html' # 保持原登录模板路径
    
  2. 更新路由配置:
    在urls.py中替换默认登录路由:

    from .views import NoCsrfLoginView
    
    urlpatterns = [
        # ...其他路由
        path('accounts/login/', NoCsrfLoginView.as_view(), name='login'),
    ]
    

    注意:此方法会关闭该视图的CSRF防护,存在被跨站伪造请求的风险,仅适合高度信任的场景。

方案三:改用DRF API实现登录(推荐)

通过Django REST Framework提供无CSRF校验的登录API,更适合跨域场景:

  1. 安装并配置DRF:

    pip install djangorestframework djangorestframework-authtoken
    

    在settings.py中添加:

    INSTALLED_APPS = [
        # ...其他应用
        'rest_framework',
        'rest_framework.authtoken',
    ]
    

    运行迁移:

    python manage.py migrate
    
  2. 添加登录API路由:

    from rest_framework.authtoken.views import obtain_auth_token
    
    urlpatterns = [
        # ...其他路由
        path('api/login/', obtain_auth_token, name='api_login'),
    ]
    
  3. 外部页面通过JS提交到API:

    const loginForm = document.querySelector('form');
    loginForm.addEventListener('submit', function(e) {
      e.preventDefault();
      const formData = new FormData(this);
      fetch('http://djangoserver.com/api/login/', {
        method: 'POST',
        body: formData
      })
      .then(res => res.json())
      .then(data => {
        if (data.token) {
          // 登录成功,可跳转到Django系统页面或存储token用于后续请求
          window.location.href = 'http://djangoserver.com/';
        } else {
          alert('用户名或密码错误');
        }
      })
      .catch(err => console.log('登录请求失败:', err));
    });
    

内容的提问来源于stack exchange,提问作者whitebear

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 22:43:05