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

桌面应用对接Django登录时出现CSRF cookie未设置403错误求助

桌面应用对接Django登录时CSRF验证失败问题

我正在开发一款桌面应用,用户可使用Django网站数据库中的凭证登录,目标是让用户通过该桌面应用在Django论坛发布帖子。目前在登录环节遇到CSRF验证失败的问题,具体细节如下:

桌面应用已实现代码

获取CSRF Token的函数

def get_csrf_token():
    
    # 向Django服务器发送GET请求获取CSRF token
    response = requests.get('http://127.0.0.1:8000/accounts/get-csrf-token/')
     
    # 检查请求是否成功(状态码200)
    if response.status_code == 200:
        # 从响应JSON中提取CSRF token
        csrf_token = response.json().get('csrf_token')
        print("CSRF TOKEN: ", csrf_token)
        return csrf_token
    else:
        # 处理请求失败的情况
        print(f"获取CSRF token失败,状态码: {response.status_code}")
        return None

登录请求代码

def login(self):

        # 从输入框获取用户名和密码
        username = self.username_input.text()
        password = self.password_input.text()   
               
        # 向Django服务器发送登录请求
        url = "http://127.0.0.1:8000/accounts/login/"
        data = {
            "username": username, 
            "password": password,
            }
        
        # 配置包含CSRF token的请求头
        headers = {
            'X-CSRFToken': get_csrf_token()
        }
        print("x-csrftoken: ", headers['X-CSRFToken'])
        response = requests.post(url, data=data, headers=headers)
        
        if response.status_code == 200:
            # 认证成功
            self.accept()
        else:
            # 认证失败
            QMessageBox.warning(self, "登录失败", "用户名或密码错误")

Django端相关配置与代码

URL路由配置

path('login/', CustomLoginView.as_view(template_name='accounts/login.html'), name='login')

Views.py核心代码

class CustomAuthenticationForm(AuthenticationForm):
    def clean_username(self):
        print("进入clean_username方法.......") 
        username = self.cleaned_data.get('username')
        if username:
            # 不区分大小写查找用户名
            return CustomUser.objects.filter(username__iexact=username).first()
        return None

class CSRFTokenView(APIView):
    authentication_classes = [SessionAuthentication]

    def get(self, request, format=None):
        print("进入get方法......")
        csrf_token = get_token(request)
        print("CSRFTokenView的get方法中的csrf token: ", csrf_token)
        return Response({'csrf_token': csrf_token})

    
class CustomLoginView(LoginView):
     
    authentication_form = CustomAuthenticationForm
    
    def get_success_url(self):
        print("进入get_success_url方法......")
        return reverse_lazy('thread_list')

Middleware配置

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

错误信息

Django返回403禁止访问错误:

Forbidden (CSRF cookie not set.): /accounts/login/
"POST /accounts/login/ HTTP/1.1" 403 2869

同时CustomAuthenticationForm和CustomLoginView中的打印语句均未执行。

已尝试的无效解决方案

  • 注释掉django.middleware.csrf.CsrfViewMiddleware中间件
  • 为CustomLoginView添加csrf_exempt装饰器
  • 为urls.py中的登录路径添加csrf_exempt
  • 移除登录模板中的{% csrf_token %}标签

解决思路

  1. 会话保持问题:当前获取CSRF Token的请求和登录请求是两个独立会话,没有共享session cookie。Django的CSRF验证要求请求携带的CSRF Token必须与会话中的CSRF Cookie对应。

    • 修改get_csrf_token函数,使用requests.Session保存会话:
      def get_csrf_token():
          session = requests.Session()
          response = session.get('http://127.0.0.1:8000/accounts/get-csrf-token/')
          if response.status_code == 200:
              csrf_token = response.json().get('csrf_token')
              print("CSRF TOKEN: ", csrf_token)
              return csrf_token, session
          else:
              print(f"获取CSRF token失败,状态码: {response.status_code}")
              return None, None
      
    • 登录函数复用同一个session发送请求:
      def login(self):
          username = self.username_input.text()
          password = self.password_input.text()   
          url = "http://127.0.0.1:8000/accounts/login/"
          data = {"username": username, "password": password}
          
          csrf_token, session = get_csrf_token()
          if not csrf_token:
              QMessageBox.warning(self, "错误", "获取CSRF token失败")
              return
          
          headers = {'X-CSRFToken': csrf_token}
          response = session.post(url, data=data, headers=headers)
          
          if response.status_code == 200:
              self.accept()
          else:
              QMessageBox.warning(self, "登录失败", "用户名或密码错误")
      
  2. CSRFTokenView认证类问题:当前CSRFTokenView使用SessionAuthentication,未登录用户无有效会话,导致生成的CSRF Token无法关联后续请求。可以移除该认证类:

    class CSRFTokenView(APIView):
        # 移除 authentication_classes = [SessionAuthentication]
        def get(self, request, format=None):
            print("进入get方法......")
            csrf_token = get_token(request)
            print("CSRFTokenView的get方法中的csrf token: ", csrf_token)
            return Response({'csrf_token': csrf_token})
    
  3. 确认Cookie传递:使用同一个requests.Session实例会自动处理cookie的保存和携带,确保登录请求中包含获取CSRF Token时返回的csrftoken cookie。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:16:05