Я работаю над приложением CodeIgniter, где использую защиту CSRF с отправкой форм AJAX. У меня есть $config['csrf_regenerate'] = TRUE; включен в моей конфигурации, но я сталкиваюсь с ошибкой 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;
}
Выход
Теперь эта проблема решена. Я решаю эту проблему, устанавливая недавно возвращенный токен 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);
}