Php CSRF如何保护发布到其他页面的表单?

Php CSRF如何保护发布到其他页面的表单?,php,forms,zend-framework,csrf,Php,Forms,Zend Framework,Csrf,我有一个关于CSRF安全性和登录表单的小问题。该表格的工作原理如下: 在主布局中,视图帮助器创建一个登录表单,并在用户经过身份验证后显示一个特定于用户的菜单 // User menu viewhelper public function authentication() { // Check if user is authenticated or not $auth = Zend_Auth::getInstance(); if(!$auth->hasIde

我有一个关于CSRF安全性和登录表单的小问题。该表格的工作原理如下:

在主布局中,视图帮助器创建一个登录表单,并在用户经过身份验证后显示一个特定于用户的菜单

    // User menu viewhelper
public function authentication()
{
    // Check if user is authenticated or not
    $auth = Zend_Auth::getInstance();

    if(!$auth->hasIdentity())
    {
        $form = new Application_Form_Login();
        $form->setAction($this->_view->url(array('action' => 'login'), 'ucp', true));

        return $form;
    }
    else
    {
        // return user specific menu
    }
}
表单发布到包含所有用户控制面板逻辑的UcpController,例如登录/注销和显示用户特定信息

    // loginAction in UcpController
public function loginAction()
{
    if(Zend_Auth::getInstance()->hasIdentity())
    {
        $this->_redirect('/');
        return;
    }

    $request = $this->getRequest();

    $form = new Application_Form_Login();

    if($request->isPost())
    {
        if($form->isValid($post = $request->getPost()))
        {
            // Do authentication stuff here.
        }
    }

    $this->view->form = $form;
}
可悲的是,这样CSRF令牌就无法匹配,我不知道如何解决这个问题。我是不是遗漏了什么?我是否应该一起删除CSRF验证

// The CSRF protection element as added to the login form
$this->addElement('hash', 'csrf',
    array(
        'ignore' => true
    )
);

提前感谢,非常感谢您的帮助:)

您的代码似乎正确,我认为问题可能出在其他地方。要调试此问题,请执行以下操作:

使用firebug检查生成的
应用程序表单\u登录
,尤其是CSRF令牌,然后在发布数据时尝试将
Zend\u Debug::dump
登录操作中的
$\u会话
$\u post
数组进行比较。您应该在发布的数据和会话数据之间找到匹配项

您应该在发送的post变量和名为
Zend\u Form\u Element\u Hash\u salt\u的会话变量之间搜索匹配项,如果值匹配,则错误在别处,您应该转储
$Form->getMessages()
,以查找它


正如虫族在评论中指出的那样,我之前的一句话是错误的。我查看了,发现ZF中的CSRF令牌每300秒更改一次,在此超时情况下,令牌过期不应成为您的问题。

问题已解决!我遇到了一个遇到同样问题的人。原因很奇怪:(ZF论坛)

当它转向我时,我的favicon返回一个HTTP 500代码,因为该文件不存在。这显然会触发新的CSRF生成。我一点也不知道为什么,但创建一个图标并将其上传到webroot解决了我的问题


至少谢谢你和我一起思考

每请求一个新的CSRF令牌真的很痛苦。每个会话的令牌就足够了,并且按照http请求实现是安全的。@zerkms我错了,在ZF中,令牌每300秒更改一次(默认情况下),我刚刚更新了答案。谢谢。这很奇怪,会话数据显示了一个空数组。我还发现view helper中“小”登录表单的令牌与正在验证的表单对象不同。很好,现在我在发布小表单时遇到了问题,并且凭据不正确,大表单加载,导致页面上加载两个相同的表单。当我提交大表单时,令牌无法再次验证。