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

Django接收Chrome扩展POST请求时出现CSRF cookie未设置错误

Django + Chrome扩展 CSRF认证失败问题解决指南

问题概述

开发Chrome扩展+Django的密码管理器时,提交表单数据到Django后端始终返回Forbidden (CSRF cookie not set.),已确认Cookie中存在csrftoken且请求携带了CSRF令牌,但问题依旧。


针对性解决建议

1. 修复请求数据格式不匹配

当前请求头设置Content-Type: application/x-www-form-urlencoded,但发送的是JSON格式数据,Django的request.POST无法解析JSON,导致CSRF验证逻辑触发失败。

修改方案:
将请求改为JSON格式,同时调整Django视图解析逻辑:

前端(content-script.js)修改:

export async function axiosaddCredentialsToDatabase(email,password,url){
  const token = await getCsrfToken()
  const axios = require('axios')
  axios.post('http://localhost:8000/add',{email,password,website: url},{
    headers: {
      'Content-Type': 'application/json',
      'X-CSRFToken': token,
      'X-Requested-With': 'XMLHttpRequest',
    },
    withCredentials:true
  }).then((response)=>{
    console.log(response)
  }).catch(err => console.error(err))
}

Django视图修改:

import json
from django.http import JsonResponse
from django.views.decorators.csrf import ensure_csrf_cookie
from django.contrib.auth.decorators import login_required

@login_required
@ensure_csrf_cookie
def add(request):
    if request.method == "POST":
        data = json.loads(request.body)
        website = data.get('website')
        username = data.get('email')
        password = data.get('password')
        
        encryptedPass = cryptography.crypto(password)
        credentials = Credentials.objects.create(email=username, password=encryptedPass)
        # 使用get_or_create简化逻辑
        website_obj, created = Website.objects.get_or_create(user=request.user, name=website)
        website_obj.credentials.add(credentials)
        
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest': 
            return JsonResponse({'message':'Credentials Add'})      
        return redirect('add')
    return render(request,'add.html')

2. 优化CSRF令牌获取逻辑

Chrome扩展的content script运行在隔离环境,直接读取Cookie可能存在权限限制,建议从响应头的set-cookie中提取令牌:

export async function getCsrfToken(){
  const axios = require('axios')
  const response = await axios.get('http://localhost:8000/get-csrf-token',{withCredentials:true})
  
  // 从set-cookie头提取csrftoken
  const cookies = response.headers['set-cookie']
  if (cookies) {
    const csrfEntry = cookies.find(c => c.startsWith('csrftoken='))
    if (csrfEntry) {
      return csrfEntry.split('=')[1].split(';')[0]
    }
  }
  // 回退到接口返回的token
  return response.data.csrfToken
}

3. 简化Django CSRF配置

移除冗余且冲突的配置,确保配置符合Django规范:

# settings.py
ALLOWED_HOSTS = ['localhost', '127.0.0.1']

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
    "http://localhost:8000",
    # 必须添加Chrome扩展的ID作为源,格式:chrome-extension://[你的扩展ID]
]

CSRF_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SAMESITE = 'None'
CSRF_COOKIE_SECURE = False  # 生产环境开启HTTPS后改为True
CSRF_COOKIE_HTTPONLY = False
CSRF_TRUSTED_ORIGINS = [
    "http://localhost:8000",
    # 同样添加Chrome扩展ID
]

4. 验证请求携带的Cookie

在Chrome开发者工具Network标签中,检查POST请求的Request Headers:

  • 确认Cookie字段包含csrftoken
  • 确认X-CSRFToken头的值与Cookie中的csrftoken完全一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 18:24:52