如何通过 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
)
);
预先致谢,非常感谢您的帮助:)
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您的代码看起来是正确的,我认为问题可能出在其他地方。要调试此问题,请执行以下操作:
使用 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 toZend_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.
问题解决了!我遇到了遇到同样问题的人。原因很奇怪: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!