我正在开发一个CodeIgniter应用程序,在该应用程序中使用CSRF保护以及AJAX表单提交.我有$connect ð ' csref_regenerate ']= True;在我的配置中启用了该功能,但我在重复提交表格时遇到了403错误.

  1. I'm fetching a new CSRF token on every form submission using security->get_csrf_hash(); ?> in my JavaScript code.
  2. 我正在将令牌名称和哈希以及AJX请求中的表单数据一起发送.
  3. 我假设这些令牌正在服务器端通过$connect ð ' csref_regenerate ']= TRUE;在我的Deliver.php中重新生成.

Problem:

  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;
}

Output output

推荐答案

这个问题现在已经解决了.我通过将从服务器新返回的CSRF令牌设置为表单的CSRF令牌来解决这个问题,以便每次提交表单时,我的表单的令牌和服务器的令牌将始终相同,并避免CSRF令牌不匹配.

形式

<form id="add_category_form" action="<?= base_url("Categories控制器/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);
}

Php相关问答推荐

为WooCommerce中的特定用户角色指定促销价格

Laravel有一个具有两个匹配字段

如果活动订阅者的购物车中有订阅项目,则在WooCommerce签出中显示通知

根据特定运输类别增加WooCommerce购物车总重量

过滤WooCommerce管理员订单列表(+HPOS)中包含其作者产品的订单

允许在WooCommerce管理员优惠券列表中显示自定义优惠券类型

WooCommerce HPOS管理订单列表中带有订单元数据的定制列

不包括WooCommerce中单独销售的产品

Symfony 6.2 IsGraned具有多个角色

Laravel服务Provider 没有向服务类注入价值

Codeigniter 4中的未定义变量$HOME

根据小计向 WooCommerce Checkout 添加佣金

单个产品页面 WooCommerce 订阅价格字符串的更改

Filament PHP v3:在禁用的表单字段上,ID 不会写入数据库

使用自定义规则进行 Livewire 验证不会显示错误

计算数组中连续值的数量

同一页面上多个组件的 Livewire 分页问题

正则表达式请帮我从内容中找到这个词

转发和非转发呼叫 - 后期静态绑定

为什么可以从 PHP 类访问 PHP Trait 的私有成员?