繁体   English   中英

Zend Form - 一页中有多个 forms 和(CSRF)令牌验证

[英]Zend Form - multiple forms in one page and (CSRF) token validations

我使用 Zend-Form 在我的项目中生成我的 forms。

第一:如何处理同一页面上多个forms,只post提交的表单?

第二:当我在同一页面上有两个 forms 时,令牌将仅验证 HTML 中最顶层呈现的表单。 第二个表单出现“令牌不匹配”错误,从而使表单无法发布。 你如何给每个表单一个不与其他表单冲突的唯一令牌?

真诚的,为什么

当我在同一页面上有两个 forms 时,令牌将仅验证 HTML 中最顶部的呈现形式。 第二个表单出现“令牌不匹配”错误,从而使表单无法发布。 你如何给每个表单一个不与其他表单冲突的唯一令牌?

当前实现无法使用多个 forms 上的令牌(请参阅initCsrfValidator )。

我建议您生成自己的令牌,将其存储在 session(带有表单 ID)中并自行验证。

我在尝试使用Zend_Form_Element_Hash在同一页面上有两个 forms 时发现了这个问题。 有两种方法可以做到这一点, 文档中都提到了这两种方法:

hash 元素的名称应该是唯一的。 我们建议对元素使用 salt 选项 - 两个具有相同名称和不同盐的哈希不会发生冲突

所以...

  1. 为每个Hash元素使用唯一名称
  2. 为每个Hash元素使用唯一的盐值

实际上,我刚刚修复了一个类似的问题,即我生成了具有 csrf 保护的相同表单的多个副本。 发生的事情是只有最后一个创建的表单具有正确的 csrf 令牌。

处理这个问题的草率方法是更改 Zend 库中的跃点(在 Zend_Form_Element_Hash 文件中),以便令牌在 1 次刷新或页面加载后不会过期。 这是解决问题的一种非常简单的方法,但只有在您知道页面将加载多少次时才有效。 这是创可贴解决方案

正确的方法是在页面加载后执行 ajax 调用以获取新的刷新令牌。 然后使用您的 javascript 库(jquery 可能是最简单的)并找到令牌的所有实例并将它们全部替换为新的。

所以就代码而言,它看起来像这样:Controller:

$form->hash->initCsrfToken();

$this->view->hash = $form->hash->getValue();

在您的 js 文件中(如果您使用的是 jquery)

$(.hash).replaceWith('HiddenHtmlPart1'.=hash.'HiddenHtmlPart2'); 重要的部分是选择器到 select 的所有隐藏元素。 然后你只需要替换隐藏元素的内部。 相同的想法适用于其他 js 库,尽管它会涉及不同的方法。

我遇到了同样的情况

当我在同一页面上有两个 forms 时,令牌将仅验证 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 非常简单,甚至更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM