2014-03-30 107 views
1

我一直在嘗試提交一個表單,它將一個Question對象添加到數據庫中。表單提交出錯:CSRF令牌無效。請嘗試重新提交表格

但每次我這樣做,錯誤「CSRF令牌無效,請嘗試重新提交表單」出現。

在我的表單的內容字段上,我已經附加了this插件,它與Stack Overflow的編輯器相同。

在我的表單標籤字段中,我附加了this其中一個用於標記自動填充。

這裏是我的控制器代碼:

/** 
* Creates a new Question entity. 
* 
* @Route("/ask", name="question_create") 
* @Method("POST") 
* @Template("VerySoftAskMeBundle:Question:ask.html.twig") 
*/ 
public function createAction(Request $request) { 
    $entity = new Question(); 
    $form = $this->createCreateForm($entity); 
    $tags = $this->getDoctrine()->getRepository('VerySoftAskMeBundle:Tag')->findAll(); 
    date_default_timezone_set('Asia/Manila'); 
    $entity->setDateOfPost(new \DateTime()); 

    $entity->setOwner($this->getUser()); 

     $form->handleRequest($request); 

     if ($form->isValid()) { 
      $em = $this->getDoctrine()->getManager(); 
      $em->persist($entity); 
      $em->flush(); 

      return $this->redirect($this->generateUrl('question_show', array('id' => $entity->getId()))); 
     } 


    return array(
     'entity' => $entity, 
     'form' => $form->createView(), 
     'tags' => $tags 
    ); 
} 

/** 
* Creates a form to create a Question entity. 
* 
* @param Question $entity The entity 
* 
* @return Form The form 
*/ 
private function createCreateForm(Question $entity) { 
    $form = $this->createForm(new QuestionType(), $entity, array(
     'action' => $this->generateUrl('question_create'), 
     'method' => 'POST', 
     'em' => $this->getDoctrine()->getEntityManager() 
    )); 

    $form->add('submit', 'submit', array('label' => 'Ask')); 

    return $form; 
} 

/** 
    * 
    * @Route("/ask", name="ask") 
    * @Security("has_role('ROLE_USER')") 
    * @Method("GET") 
    * @Template 
    */ 
    public function askAction() { 

     $tags = $this->getDoctrine()->getRepository('VerySoftAskMeBundle:Tag')->findAll(); 
     $entity = new Question(); 
     $form = $this->createCreateForm($entity); 

     return array(
      'entity' => $entity, 
      'form' => $form->createView(), 
      'tags' => $tags 
     ); 
    } 

我做了一個數據轉換器用於其原來的輸入標籤爲標籤的對象我的標籤字段。

class TagTransFormer implements DataTransformerInterface { 

/** 
* @var ObjectManager 
*/ 
private $om; 

/** 
* @param ObjectManager $om 
*/ 
public function __construct(ObjectManager $om) { 
    $this->om = $om; 
} 

/** 
* Transforms an object (issue) to a string (number). 
* 
* @return ArrayCollection 
*/ 
public function transform($tags) { 

    return $tags; 
} 

/** 
* Transforms a string (number) to an object (issue). 
* 
* @param string $number 
* 
* @return ArrayCollection 
* 
* @throws TransformationFailedException if object (issue) is not found. 
*/ 
public function reverseTransform($ids) { 

    $tags = array(); 

    if (!$ids) { 
     return null; 
    } 

    $repo = $this->om 
      ->getRepository('VerySoftAskMeBundle:Tag'); 

    $idsArray = explode(",", $ids); 
    foreach ($idsArray as $id) { 
     $tags[] = $repo->findOneByName($id); 
    } 
    return $tags; 
} 
} 

這是我的表單類:

class QuestionType extends AbstractType { 

/** 
* @param FormBuilderInterface $builder 
* @param array $options 
*/ 
public function buildForm(FormBuilderInterface $builder, array $options) { 

    $entityManager = $options['em']; 
    $transformer = new TagTransFormer($entityManager); 

    $builder 
      ->add('title', 'text') 
      ->add('content', 'textarea') 
      ->add($builder->create('tags', 'text') 
        ->addModelTransformer($transformer) 
    ); 
} 

/** 
* @param OptionsResolverInterface $resolver 
*/ 
public function setDefaultOptions(OptionsResolverInterface $resolver) { 
    $resolver->setDefaults(array(
       'data_class' => 'VerySoft\AskMeBundle\Entity\Question' 
      )) 
      ->setRequired(array(
       'em', 
      )) 
      ->setAllowedTypes(array(
       'em' => 'Doctrine\Common\Persistence\ObjectManager', 
    )); 
} 

/** 
* @return string 
*/ 
public function getName() { 
    return 'verysoft_askmebundle_question'; 
} 
} 

我的嫩枝模板:

<div id="askDiv" style="padding-bottom: 90px;"> 
     {{ form_start(form, { 'attr' : { 'novalidate' : 'novalidate', 'class' : 'col-md-offset-3 form-control-static col-md-7' } }) }} 
<div class="col-lg-12" style="padding: 0px; margin-bottom: 30px;"> 
    <span class="askLabels col-lg-1 text-left">{{ form_label(form.title) }}</span> 
      {{form_widget(form.title, { 'attr' : { 'class' : 'form-control col-lg-11' } })}} 
</div> 
     {{ form_widget(form.content, { 'attr' : { 'class' : 'col-lg-12' } }) }} 
<div class="col-lg-12" style="padding: 0px; margin-top: 20px;"> 
    <label class="col-lg-1 text-left askLabels" for="tagField">Tags</label> 

    <div class="col-lg-8"> 
     {{ form_widget(form.tags) }} 
    </div> 
    {% if app.user.reputation >= 100 %} 
    <a id="addTag" title="Add New Tag" data-toggle="tooltip modal" data-placement="left" class="col-lg-3" href="#"><i class="fa fa-plus-circle"></i></a> 
    <div id="mymodal" class="modal fade bs-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true"> 
     <div class="modal-dialog"> 
      <div class="modal-content"> 
       <div class="modal-header"> 
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> 
        <h4 class="modal-title" id="myModalLabel">Add New Tag</h4> 
       </div> 
       <div class="modal-body"> 
        <label for="tagName">Tag Name: </label> 
        <input id="tagName" class="form-control" type="text"/> 
       </div> 
       <div class="modal-footer"> 
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> 
        <button type="button" class="btn btn-primary">Add Tag</button> 
       </div> 
      </div> 
     </div> 
    </div> 

    {% endif %} 


</div> 
<div style="margin-top: 20px; "> 
     {{ form_widget(form.submit, { 'attr' : { 'class' : 'col-md-offset-4 col-md-4 btn btn-primary' } }) }} 
</div> 

<p> 
    title error{{ form_errors(form.title) }} 
</p> 
<p> 
    content error{{ form_errors(form.content) }} 
</p> 
<p> 
    tag error{{ form_errors(form.tags) }} 
</p> 
<p> 
    form error{{ form_errors(form) }} 
</p> 

腳本:

$(document).ready(function(){ 
$("textarea").pagedownBootstrap(); 

    var zeTags = ["{{ tags|join('", "')|raw }}"]; 
    $('#verysoft_askmebundle_question_tags').tagit({ 
     availableTags: zeTags, 
     tagLimit: 5, 
     beforeTagAdded: function(event, ui) { 
      if ($.inArray(ui.tagLabel, zeTags) == -1) 
       return false; 
     } 
    }); 
}); 

回答

5

你錯過了

{{ form_rest(form) }} 

Symfony2中有一種機制,有助於防止跨站點腳本:它們產生具有用於表單驗證一個CSRF令牌。在這裏,在你的例子中,你不顯示(所以不提交)form_rest(form)。基本上form_rest(form)將「渲染」你以前沒有渲染過但包含在你傳遞給視圖的表單對象中的每個字段。 CSRF令牌就是其中的一個值。

+0

嘿,這工作。謝謝! – schizoskmrkxx

+0

不客氣:) – DonCallisto

3

對於較新版本的Symonfy,例如2.4+你會使用新的form_end(form),它會自動呈現所有未渲染的字段以及CSRF標記。

documentation

form_end() - Renders the end tag of the form and any fields that have not yet been rendered. This is useful for rendering hidden fields and taking advantage of the automatic CSRF Protection. 
相關問題