如何CSRF保护发布到另一个页面的表单?

时间:2011-08-18 13:42:53

标签: 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->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
    )
);

在此先感谢,非常感谢您的帮助:)

2 个答案:

答案 0 :(得分:0)

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

使用firebug检查生成的Application_Form_Login,特别是CSRF令牌,然后在发布数据时尝试Zend_Debug::dump您的loginAction中的$_SESSION$_POST数组比较结果。您应该在发布的数据和会话数据之间找到匹配项。

您应该搜索已发送的post变量和名为Zend_Form_Element_Hash_salt_<name-of-your-element>的会话变量之间的匹配项,如果值匹配,则错误发生在其他地方,您应该转储$form->getMessages()以找到它。

正如zerkms在评论中指出的那样,我之前的判决是错误的。我查看了implementation,我发现ZF中的CSRF令牌在300秒内改变了一次,这个超时令牌到期应该不是您的问题。

答案 1 :(得分:0)

问题解决了!我遇到了遇到同样问题的人。原因很奇怪:http://tinyurl.com/3fkg8bk(ZF论坛)。

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

感谢至少和我一起思考!