【问题标题】:How to send CSRF Cookie from React to Django Rest Framework with Axios如何使用 Axios 将 CSRF Coo​​kie 从 React 发送到 Django Rest Framework
【发布时间】: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"

【问题讨论】:

    标签: reactjs django-rest-framework axios csrf django-csrf


    【解决方案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.))
      猜你喜欢
      • 2018-12-30
      • 2013-07-16
      • 2016-04-19
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      相关资源
      最近更新 更多