我有多个设置的管理页面,每个设置在不同的选项卡中都有不同的形式。
我正在使用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并保存数据,到目前为止,当我只有一个...
我发现了问题。