桌面应用对接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 %}标签
解决思路
会话保持问题:当前获取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, "登录失败", "用户名或密码错误")
- 修改
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})确认Cookie传递:使用同一个
requests.Session实例会自动处理cookie的保存和携带,确保登录请求中包含获取CSRF Token时返回的csrftokencookie。
内容的提问来源于stack exchange,提问作者Anton
相关产品推荐
相关产品推荐

