CodeIgniter AJAX 表单提交中的 CSRF 令牌重新生成问题

问题描述 投票:0回答:1

我正在开发一个 CodeIgniter 应用程序,其中使用 CSRF 保护和 AJAX 表单提交。我有 $config['csrf_regenerate'] = TRUE;在我的配置中启用,但我在重复表单提交时遇到 403 错误。

  1. 我使用 security->get_csrf_hash() 在每个表单提交上获取新的 CSRF 令牌; ?> 在我的 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.log(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 ajax codeigniter-3
1个回答
0
投票

这个问题现在已经解决了。我通过将服务器新返回的 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.log(formData);

            $.post(url, formData, function(response) {
                console.log(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);
}
© www.soinside.com 2019 - 2024. All rights reserved.