如何使用 Axios 将 CSRF Coo​​kie 从 React 发送到 Django Rest Framework

Posted

技术标签:

【中文标题】如何使用 Axios 将 CSRF Coo​​kie 从 React 发送到 Django Rest Framework【英文标题】:How to send CSRF Cookie from React to Django Rest Framework with Axios 【发布时间】:2019-06-03 11:36:20 【问题描述】:

我想使用 AxiosReact 应用向 Django Rest Framework 后端发出 POST 请求.我已经设法从后端获得 CSRF 令牌,但我无法将它与我的请求一起发送,所以我总是收到 Forbidden (CSRF cookie not set.) 错误:

这是我的 React 应用的代码:

handleClick() 
    const axios = require('axios');
    var csrfCookie = Cookies.get('XSRF-TOKEN');
    console.log(csrfCookie)
    axios.post('http://127.0.0.1:8000/es/api-auth/login/',
      
        next: '/',
        username: 'admin@admin.com',
        password: 'Cancun10!',
      ,
      
        headers: 
          'x-xsrf-token': csrfCookie,  // <------- Is this the right way to send the cookie?
        ,
        withCredentials = true,
      
    )
    .then(function (response) 
      console.log(response);
    )
    .catch(function (error) 
      console.log(error);
    )
  

这是我的settings.py CSRF 配置:

CORS_ALLOW_CREDENTIALS = True
CORS_ALLOW_HEADERS = (
    'xsrfheadername',
    'xsrfcookiename',
    'content-type',
    'XSRF-TOKEN',
)

CORS_ORIGIN_WHITELIST = serverconfig.CORS_ORIGIN_WHITELIST
CSRF_TRUSTED_ORIGINS = serverconfig.CSRF_TRUSTED_ORIGINS
CSRF_COOKIE_NAME = "XSRF-TOKEN"

【问题讨论】:

【参考方案1】:

另外,如果你创建一个 Axios 实例会更容易

const instance = axios.create(
  baseURL: API_URL,
  withCredentials: true,
  xsrfHeaderName: 'X-CSRFToken',
  xsrfCookieName: 'csrftoken',
)

并确保xsrfCookieNameCSRF_COOKIE_NAME 具有相同的名称。请注意,如果CSRF_COOKIE_HTTPONLY 设置为 True,客户端 javascript 将无法访问 CSRF cookie:

# settings.py

CSRF_COOKIE_NAME = "csrftoken"
CSRF_COOKIE_HTTPONLY = False

CORS_EXPOSE_HEADERS = ["Content-Type", "X-CSRFToken"]
CORS_ALLOW_CREDENTIALS = True

【讨论】:

【参考方案2】:

Django 默认使用X-CSRFTOKEN 作为 csrf 标头,参见here。您在 Django 设置中使用的选项 CSRF_COOKIE_NAME 仅更改 cookie 名称,默认情况下为 csrftoken,请参阅 here。

要解决您的问题,请在您的 axios 调用中使用此标头:headers: 'X-CSRFTOKEN': csrfCookie

使用以下内容:

axios.post('http://127.0.0.1:8000/es/api-auth/login/',
    
        next: '/',
        username: 'admin@admin.com',
        password: 'Cancun10!',
    ,
    
        headers: 
             'X-CSRFTOKEN': csrfCookie,
         ,
    ,
)

另外,在您的 Django 设置中从 CORS_ALLOW_HEADERS 中删除 XSRF-TOKEN,然后将 X-CSRFTOKEN 添加到其中。如果您不想删除 XSRF-TOKEN,可以使用以下文档安全地将 X-CSRFTOKEN 添加到 CORS_ALLOW_HEADERS,文档 here

# settings.py

from corsheaders.defaults import default_headers

CORS_ALLOW_HEADERS = list(default_headers) + [
    'X-CSRFTOKEN',
]

【讨论】:

我试了你的回答,后端没有报错(这是后端控制台结果:"OPTIONS /es/api-auth/login/ HTTP/1.1" 200 0),但是前端控制台报错:Access to XMLHttpRequest at 'http://127.0.0.1:8000/es/api-auth/login/' from origin 'http://localhost:3000' has been blocked by CORS policy: Request header field x-csrftoken is not allowed by Access-Control-Allow-Headers in preflight response跨度> @HugoLuisVillalobosCanto 尝试在 Django 设置中将X-CSRFTOKEN 添加到CORS_ALLOW_HEADERS 我做到了,又回到了原点(Forbidden (CSRF cookie not set.) @HugoLuisVillalobosCanto 尝试将 withCredentials: True 添加到 axios 配置中(在标题之后)。 我犯了一个错误。现在它正在工作,但我收到另一个错误:Forbidden (CSRF token missing or incorrect.))

以上是关于如何使用 Axios 将 CSRF Coo​​kie 从 React 发送到 Django Rest Framework的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS 和 Django:如何以正确的方式使用 axios 发送 csrf 令牌?

Express + React:CSRF Coo​​kie 在生产中未定义,在本地工作

Laravel 6 会话和 CSRF Coo​​kie 未设置——每次页面加载的会话数据库中的新条目

带有 axios 和 vue 的 laravel 5.8 中的 CSRF

Django CSRF 和 axios 发布 403 Forbidden

无法使用 axios 向 Laravel 应用程序发帖