«Запрещено (токен CSRF отсутствует или неверен):» с использованием Django и JS

Я делаю запрос POST, используя Axios в своем JS-коде, чтобы отправить некоторую информацию на мой локальный сервер Django. У меня есть {% csrf_token %} в форме html-кода, но я не знаю, как отправить токен csrf с помощью Axios.

Я получаю эту ошибку в терминале: «Запрещено (токен CSRF отсутствует или неверен.): /api/scoring/submit_score_details».

Как мне правильно вставить токен csrf в мой пост axios? Прямо сейчас я не думаю, что JS может читать {{ csrf_token }}, как у меня. Я искал Stack, но кажется, что большинство людей используют jQuery или какой-либо другой тип JS.

Чтобы сэкономить место, я не стал публиковать переменные в полезной нагрузке, но все они просто строки.

Я могу избавиться от ошибки, если поставлю @csrf_exempt над моей функцией в файле views.py.

{
let payload = {
    "csrfmiddlewaretoken": "{{ csrf_token }}",
    "math_problem": problem,
    "user_answer": userInput,
    "true_answer": correctAnswer,
    "question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
<div class = "col text-center">
    <button id = "start" type = "button" class = "btn btn-primary btn-lg">
        New Problem
    </button>
    <p id = "math_problem"></p>
    <form id = "inputForm" method = "POST">
        {% csrf_token %}
        <input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
        <input id = "correct_answer" type = "hidden">
    </form>
    <br>
    <button id = "result_check" type = "button" class = "btn btn-primary btn-lg">Check</button>
    <script src = {% static 'js/game_logic.js' %}></script>
</div>

{
let payload = {
    "csrfmiddlewaretoken": "{{ csrf_token }}",
    "math_problem": problem,
    "user_answer": userInput,
    "true_answer": correctAnswer,
    "question_status": questionStatus,
}
console.info(payload);
axios.post('../api/scoring/submit_score_details', payload)
}
<form id = "inputForm" method = "POST">
    {% csrf_token %}
    <input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
    <input id = "correct_answer" type = "hidden">
</form>
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
3 557
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Возможно ли, что ваш код Axios создается до того, как csrf_token отображается на странице (по шаблону django)?

Попробуйте что-то подобное в начале кода js:

var my_token = '{{ csrf_token }}';

затем, когда вы вызываете Axios, отправьте это значение вместо рендеринга {{ csrf_token }} в строке, так что-то вроде этого:

{
    let payload = {
        "csrfmiddlewaretoken": my_token,
        "math_problem": problem,
        "user_answer": userInput,
        "true_answer": correctAnswer,
        "question_status": questionStatus,
    }
    console.info(payload);
    axios.post('../api/scoring/submit_score_details', payload)
}

Мне также любопытно, видели ли вы, что ваш токен csrf печатается на консоли в коде, который вы показали (из распечатки полезной нагрузки), поскольку это указывало бы, был ли он отправлен или нет.

Если отправлялся csrf_token, возможно, с приложением возникла какая-то другая проблема, но как только у вас есть токен в my_token, вы можете распечатать его и убедиться, что он настроен правильно, и работать оттуда.

Попробовал ваш метод, но без кубиков. Я получаю ту же ошибку. Я не думаю, что JS знает, что такое {{ csrf_token }}. Токен не выводится в консоли. Вот как выглядит пример полезной нагрузки: csrfmiddlewaretoken: "{{ csrf_token }}" math_problem: "4 x 1" question_status: "correct" true_answer: "4" user_answer: "4"

Hiebs915 09.12.2020 23:21

Используете ли вы Django для вывода вывода (это то, что переводит {{ csrf_token }} в требуемую строку? Вот почему я предложил загрузить токен в свою собственную переменную, чтобы его можно было перепроверить. Если вы не используя django для рендеринга html, тогда как вы его настроили?

GoGoWorx 09.12.2020 23:22

Да, HTML отображается с помощью Django. Мой JS также находится в моем проекте Django, внутри моей статической папки.

Hiebs915 09.12.2020 23:26

Хм, странно, что он не конвертирует для вас {{ csrf_token }}. Внутри формы он использует {% csrf_token %} для инициализации значения (и делает его доступным для JS), но возможно ли, что ваш код генерируется до отображения формы - вы упомянули, что это в статическом коде - возможно, переместите Axios позвоните в свою форму (временно) после {% csrf_token %}, чтобы увидеть, делает ли это ее счастливее - я полагаю, что столкнулся с подобной проблемой некоторое время назад, поэтому я предложил создать переменную "раньше" в вашем JS. Вы также можете установить точку останова, чтобы проверить ее значение.

GoGoWorx 09.12.2020 23:31

что именно я должен добавить в свой HTML из моего JS-файла? JS POST использует множество переменных и других элементов, которые являются частью файла JS.

Hiebs915 09.12.2020 23:38

Похоже, вы можете просто поместить вызов Axios (как показано выше, пусть полезная нагрузка... axios post...) в свой HTML. Вам, очевидно, нужно будет поместить его в тег <script>, но таким образом вы сможете сделать вызов axios и увидеть токен csrf, поскольку токен должен быть действительным в вашей форме. Если это поможет, я много раз использовал подобные методы для рендеринга токена, поэтому я знаю, что это работает. Вы можете использовать фиктивные значения для параметров полезной нагрузки, если вам нужно во время этого теста.

GoGoWorx 09.12.2020 23:41

Хорошо, оглядываясь назад на обсуждение, я думаю, что могу знать, что здесь происходит...

Возможно, вы добавили "{{ csrf_token }}" в свой JS (где-то хранится в статическом коде) - это не сработает, поскольку, как вы указали, JS ничего не знает о шаблонах django.

Это можно сделать, изменив код JS так, чтобы он использовал переменную JS (например, my_token).

{
    let payload = {
        "csrfmiddlewaretoken": my_token, // populated later within form
        "math_problem": problem,
        "user_answer": userInput,
        "true_answer": correctAnswer,
        "question_status": questionStatus,
    }
    console.info(payload);
    axios.post('../api/scoring/submit_score_details', payload)
}

Это значение my_token будет предоставлено позже (в вашей форме) перед вызовом Axios. Для этого добавьте в форму:

<script>
    // This will be rendered by Django to get the actual string into my_token
    var my_token = "{{ csrf_token }}"; 
</script>

Затем, когда ваш вызов Axios будет выполнен (нажатием кнопки, таймера или чего-то еще), эта глобальная переменная должна быть правильно установлена ​​и использована.

Поместить это до или после моего JS-скрипта в нижней части моего div?

Hiebs915 09.12.2020 23:49

Вы можете поместить его прямо под {% csrf_token %}, чтобы было понятно, что происходит, если хотите.

GoGoWorx 09.12.2020 23:51

Получил новую информацию! Я забыл удалить "var my_token" {{csrf_token}} в верхней части JS. Я удалил его, и теперь в консоли выводится строка токена.

Hiebs915 10.12.2020 00:01
Ответ принят как подходящий

В итоге я погуглил и спросил у друга. Мы придумали решение.

Нам пришлось добавить две строки кода, чтобы все заработало:

axios.defaults.xsrfCookieName = 'csrftoken';
axios.defaults.xsrfHeaderName = 'X-CSRFToken';

Мы также избавились от переменной «полезная нагрузка» и просто поместили все в код Axios.

{
        axios.defaults.xsrfCookieName = 'csrftoken';
        axios.defaults.xsrfHeaderName = 'X-CSRFToken';
        axios.post('../api/scoring/submit_score_details', {
            "math_problem": problem,
            "user_answer": userInput,
            "true_answer": correctAnswer,
            "question_status": questionStatus,
        });
        console.info(`Problem:${problem},
                     User Input: ${userInput},
                     Correct Answer: ${correctAnswer},
                     Question Status: ${questionStatus}`
                     );
    };
<div class = "col text-center">
    <button id = "new_problem_button" type = "button" class = "btn btn-primary btn-lg">
        New Problem
    </button>
    <p id = "math_problem"></p>
    <form id = "inputForm" method = "POST">
        {% csrf_token %}
        <input id = "user_input" autocomplete = "off" class = "form-control form-control-lg" type = "text" placeholder = "Type your answer here">
        <input id = "correct_answer" type = "hidden">
    </form>
    <br>
    <button id = "result_check" type = "button" class = "btn btn-primary btn-lg">Check</button>
    <script src = {% static 'js/game_logic.js' %}></script>
</div>

Вот ссылка, которая нам помогла.

Другие вопросы по теме