为什么我不能在对 Django REST API 的请求中设置 X-CSRFToken?

Why I can't set X-CSRFToken in request to Django REST API?

好吧,我已经尝试解决这个问题两天了,但我无法弄清楚问题出在哪里,您对测试、阅读或解决方案的建议将不胜感激,解释如下:

我正在制作 chrome 扩展以将一些数据添加到 Django REST API,在 POST 请求时将 @csrf_exempt 装饰器添加到视图时它工作正常由 chrome 扩展生成,当 POST 请求来自同一域时,即使我删除了 @csrf_exempt 装饰器(本地服务器),但是当我尝试创建 POST 来自我的扩展程序的请求我收到此服务器错误:Forbidden (CSRF cookie not set.) 但实际上我将 X-CSRFToken header 添加到我的请求中,我甚至硬编码了令牌,但服务器仍然告诉 CSRF 令牌不存在。

我已经在使用 django-cors-headers-multi 1.2.0 并且 POST 来自外部域的请求在不需要 CSRF 检查时有效。

我查看以下链接:

Django X-CSRFToken have been set but still get 403 forbidden --> 但我没有发出 XML 请求,我应该尝试发出一个吗? (我从来没有做过,我想节省时间所以我现在不想学)

https://pypi.org/project/django-cors-headers-multi/ --> 我已经添加了 CORS_ALLOW_CREDENTIALS = False 因为在我在 chrome 控制台上获得以下消息之前:对预检请求的响应未通过访问控制检查:响应中'Access-Control-Allow-Credentials'header的值为'',当请求的凭证模式为'include'[=24时,必须为'true' =]

这是我认为与解决此问题相关的代码: 前端(扩展代码)

    function makeRequest(value, csrf) {
  // Send data to server

  url = 'http://127.0.0.1:8000/smoke/add/';

  let request = new Request(url, {
    method: 'POST',
    credentials: 'include',
    headers: myHeaders,
    headers: {
      'Content-Type': 'text/plain',
      'X-CSRFToken': 'hardCodedToken',
    },
    body: JSON.stringify({
      info: value,
    }),
  });
  
  return request;
}

chrome.storage.sync.get('token', (csrf) => {
        request = makeRequest(contactData, csrf);
        console.log(request);
        fetch(request) // Error is here
          .then((response) => response.json())
          .then((data) => {
            if (data.error !== undefined) {
              alert('Este nombre de contacto ya existe');
            } else {
              console.log(data.contact);
            }
          });
      });

这是我获得的控制台打印:

服务器代码:

@ensure_csrf_cookie
def add_lead(request):
added = False
if request.method == 'POST':
    try:
        data = json.loads(request.body)
        
        #creates lead
        lead = Lead.objects.create(name=data['info']['name'], nick=data['info']['nick'])
        lead.save()

        #creates contact from lead
        WA_phone = None
        try:
            WA_phone = data['info']['WApn']
        except:
            pass

        phone = LeadPhone.objects.create(lead=lead, phone=data['info']['phone'], whats_app=WA_phone)

        phone.save()

        mail = LeadMail.objects.create(lead=lead, mail=data['info']['mail'])
        mail.save()

        field = LeadField.objects.create(lead=lead, field=data['info']['field'])
        field.save()

        added = True # shows status to JS fetch function

        contact = {
            'lead': lead.id,
            'name': lead.name,
            'nick': lead.nick,
            'phone': phone.phone,
            'mail': mail.mail,
            'field': field.field
        }

        ids = {
            'phone': phone.id,
            'mail': mail.id
        }


    except IntegrityError:
        return JsonResponse({'added': added, 'error': 'contacto existente'})

return JsonResponse({'added': added, 'contact': contact, 'ids': ids})

这是我收到以下错误的地方: 禁止(未设置 CSRF cookie。):/smoke/add/

这是我的 settings.py 配置 cors-headers:

CORS_ORIGIN_WHITELIST = ["https://extension.runningdomain.com"]

CORS_ALLOW_HEADERS = (
'x-requested-with',
'content-type',
'accept',
'origin',
'authorization',
'x-csrftoken'
)

CORS_ALLOW_CREDENTIALS = True

感谢大家的支持,抱歉我的英语不好。

@wOxxOm 你的建议再次帮助了我。

对于 chrome 扩展,您无法从内容脚本发出提取请求,当我将提取过程更改为后台脚本时一切正常。

所以解决方案是从后台脚本发出请求。

https://www.chromium.org/Home/chromium-security/extension-content-script-fetches