我使用Zend-Form在我的项目中生成表单。
首先:如何在同一页面上处理多个表单,并仅发布提交的表单?
第二:当我在同一页面上有两个表单时,令牌将仅验证HTML中最顶层的呈现形式。第二种形式与“令牌不匹配”错误,从而使表单无法发布。如何为每个表单提供一个与其他表单不冲突的唯一标记?
真诚地,为什么
答案 0 :(得分:6)
当我在同一页面上有两个表单时,令牌将仅验证HTML中最顶层的呈现表单。第二种形式与“令牌不匹配”错误,从而使表单无法发布。如何为每个表单提供一个与其他表单不冲突的唯一标记?
当前implementation无法使用多种表单上的代币(请参阅initCsrfValidator
)。
我建议您生成自己的令牌,将其存储在会话中(使用表单ID)并自行验证。
答案 1 :(得分:3)
我尝试使用Zend_Form_Element_Hash
在同一页面上创建两个表单时发现了这个问题。有两种方法可以实现这一点,两者都是mentioned in the documentation:
哈希元素的名称应该是唯一的。我们建议对元素使用salt选项 - 具有相同名称和不同盐的两个哈希不会发生冲突
因此...
Hash
元素使用唯一名称Hash
元素使用唯一的salt值答案 2 :(得分:0)
我遇到了与
相同的情况当我在同一页面上有两个表单时,令牌只会验证 HTML中最顶层的呈现形式。获得第二种形式 “令牌不匹配”错误,从而使表单无法发布。怎么样 你给每个表单一个唯一的标记,不与之冲突 其他
一种可能的解决方案是仅为令牌生成和验证提供单独的表单。然后在HTML中,每个表单都有自己的令牌元素,但具有相同的值。如果您提交一个表单,则使用您用于生成表单的表单验证此标记元素。如果您使用的是ajax表单和经典POST表单的混合,那么您可以在响应中发送新令牌并将其分配给每个令牌元素。
//Finally set the response token
$form->getElement('token')->render(); //Need to call render in order to regenerate the token
$response['token'] = $form->getElement('token')->getValue();
$this->_helper->json($response);
在jquery中,您可以使用$('._ token')。val(response.token)
事实上,它比为每个表单添加Zend_Form_Element_Hash简单甚至更好。
答案 3 :(得分:0)
我实际上刚刚修复了一个类似的问题,我用csrf保护生成了相同表单的几个副本。发生的事情是只有最后创建的表单才有正确的csrf令牌。
处理此问题的方法是更改Zend库中的跳(在Zend_Form_Element_Hash文件中),以便在刷新或页加载后令牌不会过期。这是解决问题的一种非常简单的方法,但只有在您知道页面加载次数时才有效。这是绑定解决方案
执行此操作的正确方法是在页面加载后执行ajax调用以获取新刷新的标记。然后使用你的javascript库(jquery可能是最简单的)并找到令牌的所有实例,并用新的实例替换它们。
所以在代码方面,它看起来像这样: 控制器:
$形式 - >散列> initCsrfToken();
$ this-> view-> hash = $ form-> hash-> getValue();
在你的js文件中(如果你使用的是jquery)
$(。hash).replaceWith('HiddenHtmlPart1'。= hash.'HiddenHtmlPart2'); 重要的部分是选择器选择所有隐藏的元素。然后你只需要替换隐藏元素的内部。同样的想法适用于其他js库,尽管它涉及不同的方法。