CakePHP 2.4:通过 SecurityComponent 获取大型、可扩展的表单?
CakePHP 2.4: Getting large, extensible forms past SecurityComponent?
使用 CakePHP (2.4) 和 SecurityComponent 提交大型可扩展表单的最安全方式是什么?
我的应用程序上有一个表单,它使用 jQuery 创建新字段来存储新子记录(和 sub-子记录)。这与 Cake 的 SecurityComponent 冲突,后者期望提交表单上的所有字段都由 FormHelper 在服务器端创建。
过去,当我只在一个关联中保存记录时,我已经能够将用户端的字段限制为一个高但可行的数字,例如 100,并明确解锁每个可能的字段表单可以生成:
while($i < 100){
$this->Form->unlockField('ChildModel.' . $i . '.value'); $i++;
// unlock other fields for that possible record
}
但是,对于这种新形式,我必须在 两个 关系中保存数据。用户可能会创建很多子记录或子记录,因此命名空间 ChildModel.[1-100].field, ChildModel.[1-100].GrandchildModel.[1-100].field
开始变得巨大。解锁一个包含 数万 个可能字段的命名空间,其中很少会被使用,但所有这些都可能需要,开始听起来真的很疯狂。
其他 CakePHP 开发人员找到了哪些解决方案来解决此问题?我想这是其他人遇到的事情,其中禁用整个操作的安全性根本不是一个选项。
我个人是这样做的:
使用AJAX将要创建的动态字段的信息发送回服务器
使用新输入生成表单
从生成的表单中提取令牌值 HTML 并将它们与生成的新字段 HTML 一起传回
将生成的 HTML 和令牌值注入现有表单
???
盈利!
这是一个来自旧项目的非常基本的剥离示例,它用于为单个关联添加额外的输入。
服务器端:
App::uses('Xml', 'Utility');
$formHtml = $this->Form->create('Model');
$this->Form->input('some_field');
$this->Form->input('also_a_field');
$dynamicInputs = array();
for($i = 0; $i < $numberOfEntries; $i ++)
{
$dynamicInputs[] = $this->Form->input('AssociatedModel.' . $i . '.field');
}
$formHtml .= $this->Form->end();
$xml = Xml::build($formHtml);
$formData = Xml::toArray($xml);
$data = array
(
'token' => array
(
'key' => array
(
'id' => $formData['form']['div'][0]['input'][1]['@id'],
'value' => $formData['form']['div'][0]['input'][1]['@value']
),
'fields' => array
(
'id' => $formData['form']['div'][2]['input'][0]['@id'],
'value' => $formData['form']['div'][2]['input'][0]['@value']
),
'unlocked' => array
(
'id' => $formData['form']['div'][2]['input'][1]['@id'],
'value' => $formData['form']['div'][2]['input'][1]['@value']
)
),
'dynamicInputs' => $dynamicInputs
);
echo json_encode($data);
前端(使用jQuery):
var form = $('#my-form');
function addEntry()
{
var inputs = form.find('.associated-model .input');
var numberOfEntries = inputs.length + 1;
$.ajax({
url: '/controller/action/whatever',
type: 'POST',
data: 'numberOfEntries=' + numberOfEntries + '&' + form.serialize(),
dataType: 'json',
success: function(data)
{
updateForm(data);
}
});
}
function updateForm(data)
{
var tokenKey = form.find('input[name=\'data[_Token][key]\']');
tokenKey.attr('id', data.token.key.id);
tokenKey.attr('value', data.token.key.value);
var tokenFields = form.find('input[name=\'data[_Token][fields]\']');
tokenFields.attr('id', data.token.fields.id);
tokenFields.attr('value', data.token.fields.value);
var tokenUnlocked = form.find('input[name=\'data[_Token][unlocked]\']');
tokenUnlocked.attr('id', data.token.unlocked.id);
tokenUnlocked.attr('value', data.token.unlocked.value);
form.find('.associated-model').empty().append(data.dynamicInputs.join('\n'));
}
使用 CakePHP (2.4) 和 SecurityComponent 提交大型可扩展表单的最安全方式是什么?
我的应用程序上有一个表单,它使用 jQuery 创建新字段来存储新子记录(和 sub-子记录)。这与 Cake 的 SecurityComponent 冲突,后者期望提交表单上的所有字段都由 FormHelper 在服务器端创建。
过去,当我只在一个关联中保存记录时,我已经能够将用户端的字段限制为一个高但可行的数字,例如 100,并明确解锁每个可能的字段表单可以生成:
while($i < 100){
$this->Form->unlockField('ChildModel.' . $i . '.value'); $i++;
// unlock other fields for that possible record
}
但是,对于这种新形式,我必须在 两个 关系中保存数据。用户可能会创建很多子记录或子记录,因此命名空间 ChildModel.[1-100].field, ChildModel.[1-100].GrandchildModel.[1-100].field
开始变得巨大。解锁一个包含 数万 个可能字段的命名空间,其中很少会被使用,但所有这些都可能需要,开始听起来真的很疯狂。
其他 CakePHP 开发人员找到了哪些解决方案来解决此问题?我想这是其他人遇到的事情,其中禁用整个操作的安全性根本不是一个选项。
我个人是这样做的:
使用AJAX将要创建的动态字段的信息发送回服务器
使用新输入生成表单
从生成的表单中提取令牌值 HTML 并将它们与生成的新字段 HTML 一起传回
将生成的 HTML 和令牌值注入现有表单
???
盈利!
这是一个来自旧项目的非常基本的剥离示例,它用于为单个关联添加额外的输入。
服务器端:
App::uses('Xml', 'Utility');
$formHtml = $this->Form->create('Model');
$this->Form->input('some_field');
$this->Form->input('also_a_field');
$dynamicInputs = array();
for($i = 0; $i < $numberOfEntries; $i ++)
{
$dynamicInputs[] = $this->Form->input('AssociatedModel.' . $i . '.field');
}
$formHtml .= $this->Form->end();
$xml = Xml::build($formHtml);
$formData = Xml::toArray($xml);
$data = array
(
'token' => array
(
'key' => array
(
'id' => $formData['form']['div'][0]['input'][1]['@id'],
'value' => $formData['form']['div'][0]['input'][1]['@value']
),
'fields' => array
(
'id' => $formData['form']['div'][2]['input'][0]['@id'],
'value' => $formData['form']['div'][2]['input'][0]['@value']
),
'unlocked' => array
(
'id' => $formData['form']['div'][2]['input'][1]['@id'],
'value' => $formData['form']['div'][2]['input'][1]['@value']
)
),
'dynamicInputs' => $dynamicInputs
);
echo json_encode($data);
前端(使用jQuery):
var form = $('#my-form');
function addEntry()
{
var inputs = form.find('.associated-model .input');
var numberOfEntries = inputs.length + 1;
$.ajax({
url: '/controller/action/whatever',
type: 'POST',
data: 'numberOfEntries=' + numberOfEntries + '&' + form.serialize(),
dataType: 'json',
success: function(data)
{
updateForm(data);
}
});
}
function updateForm(data)
{
var tokenKey = form.find('input[name=\'data[_Token][key]\']');
tokenKey.attr('id', data.token.key.id);
tokenKey.attr('value', data.token.key.value);
var tokenFields = form.find('input[name=\'data[_Token][fields]\']');
tokenFields.attr('id', data.token.fields.id);
tokenFields.attr('value', data.token.fields.value);
var tokenUnlocked = form.find('input[name=\'data[_Token][unlocked]\']');
tokenUnlocked.attr('id', data.token.unlocked.id);
tokenUnlocked.attr('value', data.token.unlocked.value);
form.find('.associated-model').empty().append(data.dynamicInputs.join('\n'));
}