简体   繁体   中英

Is it possible to handle a plain old HTML form with Symfony, but with CSRF token?

I'm in the process of making a Bootstrap 4 styled payment form for my app, wherein radio buttons select the payment method. In attempting to make my form via Symfony's form classes, I've found them to be too restrictive/clumsy to do what I want. I DO NOT want to mess around with Symfony form theming (I find it annoyingly verbose), I DO NOT want to use Symfony's pre-made Bootstrap theme, and I DO NOT want to use any createFormBuilder anything.

So, is there a way for me to make a plain old HTML form, but with Symfony's CSRF token? This answer seems promising, but doesn't mention CSRF protection.

According to this documentation How to Implement CSRF Protection , an attempt of solution is to use something like (in symfony 3.4 and 4) :

  • in your controller, you can have something like :
   /**
     * @Route("/names", methods={"POST"}, name="app_post_names")
     */
    public function postName(Request $request)
    {
        $name = $request->request->get('name');
        $csrfToken = $request->request->get('_csrf_token');

         if(!$this->isCsrfTokenValid('token_id', $csrfToken)) {
          // ... throw bad request
         } 

         // ... Do other thing
    }

  • Now in your template you can have something like (with your own design) :
<form action="{{ path('app_post_names') }}" method="post">
    Name : <input name="name" type="text" />
    <input name="_csrf_token" value="{{ csrf_token('token_id') }}" type="hidden" />
    <input type="submit" value="send" />
</form>

Don't use Symfony at all, and generate your own token?

You don't really need to use Symfony form theming when making a form. Myself, I always build my own form tags.

  • You want to customise your select? Can be done too
  • You want to use fields which aren't in an entity, can be done as well...

Symfony forms aren't as restrictive as you think.

You most likely don't have the "know how" about this matter.

Controller

public function customFormAction(Request $request) {
    $form=$this->createFormBuilder()
               ->setAction($this->generateUrl('route_name'))
               ->setMethod('POST')
               ->add("customField", ChoiceType::class, array(
                   'choices'=>array(
                       '1'=>'Choice 1',
                       '2'=>'Choice 2',
                       '3'=>'Choice 2',
                   ),
                   'required'=>true,
                   'mapped'=>false, //Isn't mapped to any entity
               ))
               ->getForm();

    $form->handleRequest($request);
    if($form->isSubmitted() && $form->isValid()) {
        $customField=$form->get('customField')->getData();
        //do your stuff
    }

    return $this->render('route_name', array(
        'form'=>$form->createView(),
    ));
}

Twig view

<form action="{{ form.vars.action }}" method="{{ form.vars.method }}">
    <div class="input-field">
        <select id="{{ form.customField.vars.id }}" name="{{ form.customField.vars.full_name }}" class="my_classes">
            {% for option in form.customField.vars.choices %}
                <option data-attr="my_attributes" value="{{ option.value }}">{{ option.label }}</option>
            {% endfor %}
        </select>
    </div>
    <input name="{{ form._token.vars.full_name }}" value="{{ form._token.vars.value }}" type="hidden">
</form>

With this, I'm barely using any twig templating, I still have a CSRF token and Symfony barely handle the form (it will only check CSRF token)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM