Проблема регенерации токена CSRF при отправке формы AJAX CodeIgniter

Я работаю над приложением CodeIgniter, где использую защиту CSRF с отправкой форм AJAX. У меня есть $config['csrf_regenerate'] = TRUE; включен в моей конфигурации, но я сталкиваюсь с ошибкой 403 при повторной отправке формы.

  1. Я получаю новый токен CSRF при каждой отправке формы, используя Security->get_csrf_hash(); ?> в моем коде JavaScript.
  2. Я отправляю имя токена и хэш вместе с данными формы в запросе AJAX.
  3. Я предполагаю, что токены восстанавливаются на стороне сервера с помощью $config['csrf_regenerate'] = TRUE; в моем config.php.

Проблема:

  1. Я все еще получаю ошибку 403 при многократной отправке формы. Я подозреваю, что между ожидаемым и полученным токеном может быть несоответствие.

Я ищу рекомендации о том, как лучше всего использовать защиту CSRF и регенерацию токенов в моем сценарии.

Форма

<form id = "add_category_form" method = "post">
                    <h2>Add a Category</h2>
                    <ul>
                        <li>
                            <input type = "text" name = "category_name" required>
                            <label>Category Name</label>
                        </li>
                        <li>
                            <textarea name = "description" required></textarea>
                            <label>Description</label>
                        </li>
                        <!-- FIXME: center the content of this last li tag -->
                        <!--  <li>
                            <label>Upload Images (5 Max)</label>
                            <input type = "file" name = "image" accept = "image/*">
                        </li>
                    </ul> -->
                        <button type = "button" data-dismiss = "modal" aria-label = "Close">Cancel</button>
                        <button type = "submit">Save</button>
                </form>

JQuery

<script>
    $(document).ready(function() {
        $("#add_category_form").on("submit", function(e) {
            e.preventDefault();

            let csrfTokenName = '<?= $this->security->get_csrf_token_name(); ?>';
            let csrfHash = '<?= $this->security->get_csrf_hash(); ?>'; // Assuming you have these values in your view

            let form_data = $(this).serialize() + "&" + csrfTokenName + " = " + csrfHash;

            $.post("<?= base_url('CategoriesController/process_add_category'); ?>", form_data, function(response) {
                    console.info(response);
                })
                .fail(function(jqXHR, textStatus, errorThrown) {
                    console.error("AJAX Error:", textStatus, errorThrown);
                });

            return false;
        });
    });
</script>

Метод контроллера

public function process_add_category() {
    $category_name = $this->input->post("category_name");
    echo $category_name;
}

Выход

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
0
76
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Теперь эта проблема решена. Я решаю эту проблему, устанавливая недавно возвращенный токен CSRF с сервера на токен CSRF формы, чтобы каждый раз, когда я отправляю форму, токен моей формы и токен сервера всегда были одинаковыми и избегали несоответствия токенов CSRF.

Форма

<form id = "add_category_form" action = "<?= base_url("CategoriesController/process_add_category") ?>" method = "post">
                    <input type = "hidden" name = "<?= $this->security->get_csrf_token_name() ?>" value = "<?= $this->security->get_csrf_hash() ?>" />
                    <h2>Add a Category</h2>
                    <ul>
                        <li>
                            <input type = "text" name = "category_name" required>
                            <label>Category Name</label>
                        </li>
                        <li>
                            <textarea name = "description" required></textarea>
                            <label>Description</label>
                        </li>
                        <label>Upload Images (5 Max)</label>
                        <!--  <ul>
                                <li><button type = "button" class = "upload_image"></button></li>
                            </ul> -->
                        <input type = "file" name = "image" accept = "image/*">
                    </ul>
                    <!-- FIXME: center the content of this last li tag -->
                    <button type = "button" data-dismiss = "modal" aria-label = "Close">Cancel</button>
                    <button type = "submit">Save</button>
                </form>

JavaScript

$(document).ready(function() {
        $("#add_category_form").submit(function(e) {
            e.preventDefault();
            let url = $(this).attr("action");
            let formData = $(this).serialize();
            console.info(formData);

            $.post(url, formData, function(response) {
                console.info(response);
                /* Set the returned newly created hash and name to the form's token name and value*/
                csrfName = response.csrfName;
                $("input[name='<?= $this->security->get_csrf_token_name() ?>']").val(response.newCsrfToken);
            }, "json");
            return false;
        });
    });

Контроллер

public function process_add_category()
{
    $response = array(
        "message" => "Added category successfully!",
        "csrfName" => $this->security->get_csrf_token_name(),
        "newCsrfToken" => $this->security->get_csrf_hash()
    );
    echo json_encode($response);
}

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