Codeigniter 4在AJAX模式中重用CSRF令牌



场景:

我正在开发CMS系统,我想给对象添加一些类别(页面、帖子、媒体等)。在我看来,为了保存一个新的类别,我使用Bootstrap模式中的HTML表单,该表单通过AJAX发送到我的控制器。在整个站点上启用CSRF保护。

在第一次发送数据时,我通过表单传递CSRF令牌名称和哈希。一旦被控制器中的PHP代码处理,我想在响应中传递CSRF值,这样我就可以";重复使用";模态中的表单(例如,显示错误消息或/和创建另一个类别)。

但是,我无法访问get_csrf_token_name()get_csrf_hash()方法将值传递回视图。

在我看来,admmin/category/create.php:

...
<!-- CREATE CATEGORY MODAL MODAL -->
<div class="modal" id="createCategory" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Nová kategorie</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Zavřít"></button>
</div>
<div class="modal-body">  
<form action="" method="post" id="createCategoryForm">
<input type="hidden" value="<?= csrf_hash(); ?>" name="<?= csrf_token(); ?>" id="csrf">
<div class="form-group mb-3">
<label for="title" class="form-label">Název kategorie</label>
<input type="text" class="form-control" name="title" id="title" value="">
</div>   
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" id="createCategoryConfirm">Vytvořit novou kategorii</button>
</form>
</div>

</div>
</div>
</div>
...
<script>
$('#head').on('click', '.create', function() {
$('#createCategory').modal('show');
$('#createCategoryForm').attr('action', '<?= base_url(); ?>/admin/category/create');
$('#createCategoryConfirm').click(function(e) {            
e.preventDefault();         

var url = $('#createCategoryForm').attr('action');
var csrfElement = $('#csrf');
var csrfName = csrfElement.attr('name');
var csrfHash = csrfElement.attr('value');
var categoryTitle = $('input[name=title]').val();
var data = {
[csrfName]: csrfHash,
'title': categoryTitle
};

console.log(data);
$.ajax({
type: 'ajax',
method: 'POST',
url: url,
data: data,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
headers: {'X-Requested-With': 'XMLHttpRequest'},
success: function(result) {
console.log(result); 
},
error: function(result) {
console.log(result); 
},
});
});
});

</script>

在我的控制器Category.php:


<?php
namespace AppControllersAdmin;
use AppControllersBaseController;
use AppModelsCategoryModel;
use CodeIgniterI18nTime;

class Category extends BaseController {
protected $model;
protected $validator;
protected $security;
public function __construct() { 
$this->model = new CategoryModel();
$this->validation =  ConfigServices::validation();
$this->security =  ConfigServices::security();
helper(['form', 'date', 'url']);
}
...
public function create() {
$response = [];
// This part of code returns error
// 
// $response['csrf'] = array(
//     'name' => $this->security->get_csrf_token_name(),
//     'hash' => $this->security->get_csrf_hash()
// );
$response['security'] = $this->security;

if ($this->request->isAJAX()) {
$newCategory = [
'title' => $this->request->getVar('title'),
'slug' => url_title($this->request->getVar('title')),
'author' => session()->get('id'),
'created_at' => Time::now('Europe/Prague')->toDateTimeString(),
'updated_at' => Time::now('Europe/Prague')->toDateTimeString(),
'parent' => '0'
];
$this->validation->run($newCategory, 'categoryRules');
if (!empty($this->validation->getErrors())) {
$this->model->save($newCategory);   
$response['errors'] = $this->validation->getErrors();
echo json_encode($response);
} else {
$this->model->save($newCategory);   
$response['success'] = 'New category was created';
echo json_encode($response);
}
}          
}
...

在浏览器控制台中,AJAX响应为POST http://localhost/admin/category/create 500 (Internal Server Error),具有完整响应:

code: 500
file: "D:WebXAMPPhtdocslenkaappControllersAdminCategory.php"
line: 38
message: "Call to undefined method CodeIgniterSecuritySecurity::get_csrf_token_name()"
title: "Error"

有人能看到这里的问题吗?关于如何在CI4中重用CSRF代币,有什么好的解决方案吗?我尝试将CSRF重新生成的配置值设置为true和false,但没有效果。

更新这行代码。ENVapp/config/security

CSRF再生=错误

替换为:

var data = {
[csrfName]: csrfHash,
'title': categoryTitle
};

console.log(data);
$.ajax({
type: 'ajax',
method: 'POST',
url: url,
data: data,
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
headers: {'X-Requested-With': 'XMLHttpRequest'},
success: function(result) {
console.log(result); 
},
error: function(result) {
console.log(result); 
},
});

为此:

var data = {
'title': categoryTitle
};
$.ajax({
type: 'ajax',
method: 'POST',
url: url,
data: {
[csrfName]: csrfHash,
data
},
dataType: 'json',
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
headers: {'X-Requested-With': 'XMLHttpRequest'},
success: function(result) {
console.log(result); 
},
error: function(result) {
console.log(result); 
},
});

最新更新