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

发布于 2024-11-30 06:30:05 字数 1362 浏览 1 评论 0原文

我有一个关于 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
    )
);

预先致谢,非常感谢您的帮助:)

I have a little issue concerning CSRF security and a login form. The form works as follows:

In the main layout a view helper creates a login form and will later also display a user specific menu when a user has been authenticated.

    // 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
    }
}

The form posts to a UcpController containing all the user control panel logic, such as logging in/out and displaying user specific information.

    // 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;
}

Sadly this way the CSRF token fails to match and I'm clueless how to solve this problem. Am I missing something here? Should I remove the CSRF validation all together?

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

Thanks in advance, your help is greatly appreciated :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

撑一把青伞 2024-12-07 06:30:05

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

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

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

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

Your code seems correct, I think the problem could be somewhere else. To debug this issue do this:

Using firebug inspect the generated Application_Form_Login, especially the CSRF token, then when you post the data try to Zend_Debug::dump the $_SESSION and the $_POST array in your loginAction and compare the result. You should find a match between your posted data and your session data.

You should search for a match between the sent post variable and a session variable named Zend_Form_Element_Hash_salt_<name-of-your-element>, if the values match then the error is elsewhere and you should dump $form->getMessages() to find it.

As zerkms pointed out in a comment, my previous sentence is wrong. I looked at the implementation and I saw that the CSRF token in ZF change once in 300 seconds, with this timeout a token expiration should not be the problem in your case.

小苏打饼 2024-12-07 06:30:05

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

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

至少谢谢你和我一起思考!

Problem solved! I ran into someone who encountered the same problem. The cause is very strange: http://tinyurl.com/3fkg8bk (ZF Forums).

As it turned with me, my favicon was returning an HTTP 500 code as the file was non-existent. This apparently triggers a new CSRF to be generated. I don't have the slightest clue why, but it solved my problem to create an icon and upload it to the webroot.

Thanks for thinking along with me at least!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文