Codeigniter 3多种形式,其中ajax和csrf令牌仅在一种形式上起作用

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

我有多个设置的管理页面,每个设置在不同的选项卡中都有不同的形式。

我正在使用ajax并保存数据,并且当我在页面上只有一个表单或禁用csrf令牌时,到目前为止,csrf令牌没有任何问题。

在每个ajax请求中,控制器都会生成新令牌,并将新令牌发送回给ajax,后者将使用name="csrf_token"更新隐藏字段,但使用不同的id。

提交第一个表单后,一切都很好,但是当我尝试提交其他表单时,csrf令牌不再起作用了,我收到消息“不允许您请求的操作。”即使在我重新加载页面并尝试提交其他无效的表单后,控制台输出的页面仍为403。

是否可以在同一页面上使用csrf保护的多种形式以及如何处理?

这里是代码示例带有ajax的表单

<form id="upload-icon" method="POST" enctype="multipart/form-data">
    <input type="hidden" name="csrf_token" id="csrf_token_1" value="<?php echo $this->security->get_csrf_hash(); ?>">
    <input type="file" id="favicon_image" name="favicon_image" accept=".ico">
    <button type="button" id="upload-icon-btn">Upload</button>
</form>

<form id="update-settings" method="POST">
    <input type="hidden" name="csrf_token" id="csrf_token_2" value="<?php echo $this->security->get_csrf_hash(); ?>">
    <input type="text" name="settings_one">
    <input type="text" name="settings_two">
    <input type="text" name="settings_three">
    <button type="button" id="update-settings-btn">Update settings</button>
</form>

<script>
$(document).ready(function() {
    var csrf_token = '';
    // upload favicon form
    $('#upload-favicon-form-btn').on('click', function(e) {
        e.preventDefault();

        var fd = new FormData();
        var files = $('#favicon_image')[0].files[0];
        fd.append('favicon_image', files);

        var favicon = $('#favicon_image').val();
        if (favicon == '') {
            loadModal('Warning', 'Please select <strong>favicon.ico</strong> icon file.');
        } else {
            $.ajax({
                type: 'POST',
                url: '<?php echo base_url('admin/settings/upload_ico'); ?>',
                data: fd,
                contentType: false,
                cache: false,
                processData: false,
                dataType: 'json',
                success: function(response) {
                    csrf_token = response.csrf_token;
                    $('#csrf_token_1').val(csrf_token);

                    // messages output
                },
                error: function() {
                    // error message output
                }
            });
        }
    });

    // update settings form
    $('#update-settings-btn').on('click', function(e) {
        e.preventDefault();
        $.ajax({
            type: 'POST',
            url: '<?php echo base_url('admin/settings/update_settings'); ?>',
            data: $('#update-settings').serialize(),
            dataType: 'json',
            success: function(response) {
                csrf_token = response.csrf_token;
                $('#csrf_token_2').val(csrf_token);

                // messages output
            },
            error: function() {
                // error message output
            }
        });
    });
});
</script>

设置控制器

public function update_settings()
{
    $csrf_token = $this->security->get_csrf_hash();

    $this->form_validation->set_rules('settings_one', 'Setting one', 'trim|required|xss_clean');
    $this->form_validation->set_rules('settings_two', 'Setting two', 'trim|required|xss_clean');
    $this->form_validation->set_rules('settings_three', 'Setting three', 'trim|required|xss_clean');

    if ($this->form_validation->run()) {
        if ($this->Settings_model->UpdateSettings($this->input->post('settings_one'), $this->input->post('settings_two'), $this->input->post('settings_three'))) {
            $data = array(
                'success' => true,
                'message' => 'Settings updated.',
                'csrf_token' => $csrf_token
            );
        } else {
            $data = array(
                'error' => true,
                'message' => 'Settings was not updated.',
                'csrf_token' => $csrf_token
            );
        }
    } else {
        $data = array(
            'error' => true,
            'settings_one_error' => form_error('settings_one'),
            'settings_two_error' => form_error('settings_two'),
            'settings_three_error' => form_error('settings_three'),
            'csrf_token' => $csrf_token
        );
    }

    echo json_encode($data);
}

public function upload_ico()
{
    $csrf_token = $this->security->get_csrf_hash();

    $favicon_upload_path = './upload/';

    if (isset($_FILES['favicon_image']['name'])) {
        $config['upload_path'] = $favicon_upload_path;
        $config['allowed_types'] = 'ico';

        $this->load->library('upload', $config);

        if (!$this->upload->do_upload('favicon_image')) {
            $data = array(
                'error' => true,
                'message' => $this->upload->display_errors(),
                'csrf_token' => $csrf_token
            );

        } else {
            $data = array(
                'success' => true,
                'message' => 'Favicon uploaded.',
                'csrf_token' => $csrf_token
            );
        }
    } else {
        $data = array(
            'error' => true,
            'message' => 'No file selected.',
            'csrf_token' => $csrf_token
        );
    }
    echo json_encode($data);
}

Config.php

$config['csrf_protection'] = TRUE;
$config['csrf_token_name'] = 'csrf_token';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
$config['csrf_regenerate'] = TRUE;
$config['csrf_exclude_uris'] = array(
    'admin/settings'
);

我有多个设置的管理页面,每个设置在不同的选项卡中具有不同的形式。我正在使用ajax并保存数据,到目前为止,当我只有一个...

ajax codeigniter-3 csrf-token
1个回答
0
投票

我发现了问题。

© www.soinside.com 2019 - 2024. All rights reserved.