Запрещено (CSRF-куки не установлены) при отправке куки из react axios в django backend

Строим простую аутентификацию пользователей с помощью React и Django, но на данный момент удалось создать только реестр. Я пытался заставить это работать в течение нескольких часов и очень расстроился. Сторона react построена и страница регистрации запускается с порта django 8000.

Сервер разработки получает cookie и отлично устанавливает его на порт 8000 локального хоста. Я помещаю его в скрытое поле ввода в форме регистрации, затем получаю куки с помощью js-cookie в auth.js (я могу видеть это с помощью console.log). Затем я отправляю его с помощью axios с куки в заголовке с withCredentials=true. Я получаю следующую ошибку:

error

Forbidden (CSRF cookie not set.): /accounts/register
[28/Feb/2024 19:39:57] "POST /accounts/register HTTP/1.1" 403 2869

Я пробовал различные другие способы отправки cookie. У меня установлены все соответствующие настройки CORS.

views.py

@method_decorator(ensure_csrf_cookie, name='dispatch')
class GetCSRFToken(APIView):
    permission_classes = (permissions.AllowAny, )

    def get(self, request, format=None):
        return Response({ 'success': 'CSRF cookie set'})

auth.js

import axios from 'axios';
import {
    REGISTER_SUCCESS,
    REGISTER_FAIL
} from './types';
import Cookies from 'js-cookie'

export const register = (username, password, re_password) => async dispatch => {

    const config = {
        withCredentials: true,
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json',
            'X-CSRFToken': Cookies.get('csrftoken')
        }
    };

    const body = JSON.stringify({ username, password, re_password });

    try {

        const res = await axios.post(`${process.env.REACT_APP_API_URL}/accounts/register`, body, config);

        if (res.data.error) {
            dispatch({
                type: REGISTER_FAIL
            });
        } else {
            dispatch({
                type: REGISTER_SUCCESS
            })
        }
    } catch (err) {
        dispatch({
            type: REGISTER_FAIL
        });
    }
}

CSRFToken.js (возьмите отсюда токен csrf. Это работает)

import React, { useState, useEffect} from 'react'
import axios from 'axios'

const CSRFToken = () => {
    const [csrftoken, setcsrftoken] = useState('');

    const getCookie = (name) => {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            let cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                let cookie = cookies[i].trim();

                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }

    useEffect(() => {
        const fetchData = async () => {
            try {
                const response = await axios.get(`${process.env.REACT_APP_API_URL}/accounts/csrf_cookie`)

                setcsrftoken(getCookie('csrftoken'));
            } catch (err) {
                console.log("error");
            }
        }
        fetchData();
        
    }, []);
    
  return (
    <input type="hidden" name="csrfmiddlewaretoken" value={csrftoken} />
  );
}

export default CSRFToken

В конфигурации Axios со значениями по умолчанию для защиты от подделки межсайтовых запросов (XSRF) можно задать свойства xsrfHeaderName и xsrfCookieName. Эти свойства задают имена HTTP-заголовка и cookie, которые будут использоваться для передачи маркера межсайтовой подделки запросов.

axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";

Я решил проблему. Это была моя ошибка. В моих урлах было следующее:

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('sheetmusic.urls'))
]

urlpatterns += [re_path(r'^.*', TemplateView.as_view(template_name='index.html'))]

Шаблон catch all url, предназначенный для рендеринга моего фронтенда после сборки, перехватывал запросы к почте из-за несоответствия url. Это приводило к тому, что я не понимал ошибки несоответствия url, поскольку получал 403 Forbidden, а ошибка включала ошибочный путь, который я интерпретировал как правильный путь.

Вернуться на верх