2013-02-23 63 views
11

我創建了一個Symfony2表單並將其綁定到請求。在繼續執行表單的其餘部分之前,我需要明確確認CSRF令牌是否有效/無效。如何在Symfony2中檢查提供的CSRF令牌是否無效?

$form['_token']->isValid()引發OutOfBoundsException帶有消息「Child _token does not exist」。

我仍然可以驗證呈現的表單是否包含_token字段。如果CSRF值無效,則$form->isValid()返回false。

我在這裏錯過了什麼?


更新1:

控制器(部分):

private function buildTestForm() { 
    $form = $this->createFormBuilder() 
      ->add('name','text') 
      ->getForm(); 
    return $form; 
} 

/** 
* @Route("/test/show_form", name="test.form.show") 
* @Method("GET") 
*/ 
public function showFormTest() 
{ 
    $form = $this->buildTestForm(); 
    return $this->render('TestBundle::form_test.html.twig', array('form' => $form->createView())); 
} 

/** 
* @Route("/test/submit_form", name="test.form.submit") 
* @Method("POST") 
*/ 
public function formTest() 
{ 
    $form = $this->buildTestForm(); 
    $form->bind($this->getRequest()); 
    if ($form['_token']->isValid()) { 
     return new Response('_token is valid'); 
    } else { 
     return new Response('_token is invalid'); 
    } 
} 

模板

{# Twig template #} 
<form action="{{ path('test.form.submit') }}" method="post" {{ form_enctype(form) }}> 
    {{ form_widget(form) }} 
    <input type="submit" name="go" value="Test Form" /> 
</form> 
+0

您至少缺少表格代碼。 – mpm 2013-02-23 19:50:25

+0

@mpm,true - 現在添加完整的代碼來重現問題。 – 2013-02-23 21:56:15

+0

CSRF令牌驗證自動完成http://symfony.com/doc/current/book/forms.html#csrf-protection – 2013-02-23 22:00:20

回答

10

有到令牌手動CSRF檢查沒有任何記載的方法。 Symfony自動驗證此令牌的存在和準確性。 http://symfony.com/doc/current/book/forms.html#csrf-protection

但是有一個CSRF提供商:

http://api.symfony.com/2.0/Symfony/Component/Form/Extension/Csrf/CsrfProvider/SessionCsrfProvider.html

http://api.symfony.com/master/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.html

商標類能夠提供CSRF保護可以通過使用產生CSRF 令牌方法generateCsrfToken()。對於這種方法,您應該傳遞一個對於CSRF攻擊應保護的頁面唯一的值 。這個值不一定是 的祕密。這個接口的實現負責添加更多的祕密信息 。

如果你想確保表單提交反對CSRF攻擊,你可以提供一個「意向」字符串。通過這種方式,您可以確保 表單只能綁定到設計用於處理表單的頁面,即 ,即使用相同的意向字符串以isCsrfTokenValid()驗證CSRF標記 。

可以檢索這樣

$csrf = $this->get('form.csrf_provider'); 

使用提供商則可以使用

public Boolean isCsrfTokenValid(string $intention, string $token) 

Validates a CSRF token. 

參數字符串$意向產生 CSRF令牌串時使用的意圖$令牌令牌由瀏覽器提供

返回值布爾型瀏覽器提供的令牌是否爲 正確

您需要找出表單使用的意圖字符串。

上SO一些有趣的帖子:

Symfony CSRF and Ajax

Symfony2 links with CSRF token

+3

從Symfony 2.4開始不推薦使用''''security.csrf.token_manager'''。 http://api.symfony.com/2.7/Symfony/Component/Security/Csrf/CsrfTokenManagerInterface.html – 2014-12-17 07:24:34

0

我不知道這一點,但你嘗試過對未映射場驗證:

$violations = $this->get('validator')->validatePropertyValue($entity, '_token', $form['_token']); 
if (count($violations)) { 
    // the property value is not valid 
} 
9

另外以圖片爲準,你可以指定一個意圖:

嫩枝:

<form method="post"> 
    <input type="text" name="form_name[field]" value="" /> 
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('form_name') }}"> 
</form> 

PHP:

$token = $request->request->get('_csrf_token'); 
$csrf_token = new CsrfToken('form_name', $token); 
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token)); 

還是不行:

嫩枝:

<form method="post"> 
    <input type="text" name="field" value="" /> 
    <input type="hidden" name="_csrf_token" value="{{ csrf_token('') }}"> 
</form> 

PHP:

$token = $request->request->get('_csrf_token'); 
$csrf_token = new CsrfToken('', $token); 
var_dump($this->get('security.csrf.token_manager')->isTokenValid($csrf_token)); 
+0

ajax請求應該重新生成令牌嗎? – danidacar 2015-06-24 12:17:42

+0

ajax是一樣的嗎?! – user3746259 2016-03-30 10:17:43

+0

您可以在ajax中重新生成令牌並更新您的輸入值: 'public function tokenAction($ intention){$ csrf = $ this-> get('security.csrf.token_manager'); $ token = $ csrf-> refreshToken($ intention);返回新的響應($ token); }' – 2017-03-02 11:54:53