在链接上使用CSRF令牌

时间:2017-02-03 06:23:32

标签: symfony

我有一个关于在链接上使用CSRF令牌的问题。就我而言,我想用CSRF令牌保护我的删除链接。我找到了怎么做:

在我看来,我使用twig csrf_token()函数(http://symfony.com/doc/current/reference/twig_reference.html#csrf-token):

if (!$this->isCsrfTokenValid('deleteTube-'.$tube->getId(), $request->get('token'))) {
  $this->addFlash('warning', 'The token is not valid !');
}

在我的控制器中,isCsrfTokenValid()方法(http://symfony.com/doc/current/controller/csrf_token_validation.html):

$separator = md5(time());
$eol = "\r\n";
$message="";  // Always empty
$mailmessage="<h1>Yes got it</h1>";  //html content

$headers = "From: ".$email.$eol;
$headers .= "Bcc:". $Bcc. "\n";
$headers .= "Cc:". $cc. "\n"; 
$headers .= "Return-Path: <".$email.">\n";
$headers .= "MIME-Version: 1.0" . $eol;
$headers .= "Content-Type: multipart/mixed; boundary=\"" . $separator . "\"" . $eol;
$headers .= "Content-Transfer-Encoding: 7bit" . $eol;

$body .= "--" . $separator . "\r\n";
$body .= "Content-type:text/plain; charset=iso-8859-1\r\n";
$body .= "Content-Transfer-Encoding: 7bit\r\n";
$body .= $message . "\r\n";

$body = "--" . $separator . $eol;
$body .= "Content-type: text/html; charset=\"utf-8\"\r\n";
$body .= "Content-Transfer-Encoding: 8bit\r\n\r\n";
$body .= $mailmessage . $eol.$eol;

$body .= "--" . $separator . $eol;
$body .= "Content-Type: application/octet-stream; name=\"" . $file . "\"" . $eol;
$body .= "Content-Transfer-Encoding: base64" . $eol.$eol;
$body .= "Content-Disposition: attachment" . $eol;
$body .= $content . $eol;
$body .= "--" . $separator . "--";

mail($to, $subject, $body, $headers);

所有这些工作都很好,但我对CSRF令牌有一个普遍的问题,正如你所看到的,我为每个删除链接使用不同的令牌(例如:deleteTube-1,deleteTube-2,... with token-id中的对象Id)。然后,在我的会话中,我创建了很多csrf标记。

这是一个好方法,还是我应该为一个类的所有删除链接使用相同的标记?使用token_id,例如:deleteTube for Tube,deleteComment for Comment等等?我认为最好为每个链接设置一个不同的令牌,但也许这是开销?

非常感谢你的帮助。

PS:对不起我的英文......: - (

2 个答案:

答案 0 :(得分:0)

您可以为每个链接呈现JavaScript确认框。在你的控制器中:

private function createDeleteForm(Article $article)
{
    return $this->createFormBuilder()
        ->setAction($this->generateUrl('news_delete', array('id' => $article->getId())))
        ->setMethod('DELETE')
        ->add(
            'submit',
            'Symfony\Component\Form\Extension\Core\Type\SubmitType',
            ['label'=>'Delete', 'attr' => ['onclick'=>'return confirm("Are you sure?")', 'class' => 'btn btn-danger']]
        )
        ->getForm()
    ;
}

答案 1 :(得分:0)

CSRF保护是为了确保用户自愿采取行动。 您不需要为每个对象生成1个令牌,因为CSRF保护的目的不是区分对象,每个操作只需一个令牌即可。

来自OWASP - CSRF

跨站点请求伪造(CSRF)是一种攻击,它迫使最终用户在当前经过身份验证的Web应用程序上执行不需要的操作。


关于 Symfony
如果您为所有链接生成单个令牌,则它们具有相同的令牌值,并且不会在每次csrf_token()调用时更改。
另外,根据您的应用及其功能,还需要检查用户的权限,以通过role(例如,用户是管理员,他可以删除所有评论)或voter删除某些内容。 (例如,如果用户是作者,则用户可以删除评论。)