Запрещено (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, а ошибка включала ошибочный путь, который я интерпретировал как правильный путь.