1
votes

I generated the module "picture" and now I'm trying to call the action "delete" this way:

frontend_dev.php/picture/delete/id/1

But I get this error:

500 | Internal Server Error | sfValidatorErrorSchema

_csrf_token [Required.]

stack trace at () in SF_ROOT_DIR/lib/vendor/symfony/lib/validator/ sfValidatorSchema.class.php line 110 ...

$clean  = array();

$unused = array_keys($this->fields);

$errorSchema = new sfValidatorErrorSchema($this);

// check that post_max_size has not been reached

if (isset($_SERVER['CONTENT_LENGTH']) && (int) $_SERVER['CONTENT_LENGTH'] > $this-

getBytes(ini_get('post_max_size')))

at sfValidatorSchema->doClean(array('_csrf_token' => null)) in SF_ROOT_DIR/lib/vendor/symfony/lib/validator/ sfValidatorSchema.class.php line 90 ... */

public function clean($values)

{

return $this->doClean($values);

}

/** at sfValidatorSchema->clean(array('_csrf_token' => null)) in SF_ROOT_DIR/lib/vendor/symfony/lib/form/sfForm.class.php line 247 ...

Any idea?

Regards

Javi

sf 1.4

3

3 Answers

-1
votes

If you call delete action through "Delete" button in form or list, then you can try to update buggy function _method_javascript_function() in UrlHelper.php to this version

function _method_javascript_function($method)
{
    $function = "var f = document.createElement('form'); f.style.display = 'none';     this.parentNode.appendChild(f); f.method = 'post'; f.action = this.href;";
    $varFlag = false;

    if ('post' != strtolower($method))
    {
        $varFlag = true;
        $function .= "var m = document.createElement('input'); m.setAttribute('type', 'hidden'); ";
        $function .= sprintf("m.setAttribute('name', 'sf_method'); m.setAttribute('value', '%s'); f.appendChild(m);", strtolower($method));
    }

    // CSRF protection
    $form = new BaseForm();
    if ($form->isCSRFProtected())
    {
        $function .= ($varFlag ? '' : 'var ')."m = document.createElement('input'); m.setAttribute('type', 'hidden'); ";
        $function .= sprintf("m.setAttribute('name', '%s'); m.setAttribute('value', '%s'); f.appendChild(m);", $form->getCSRFFieldName(), $form->getCSRFToken());
    }

    $function .= "f.submit();";

    return $function;
}
1
votes

I would highly recommend AGAINST commenting out the CSRF protection as suggested by dxb. Because then anyone will be able to access that deletion url and delete stuff from your database. Even if you limit the route to post methods, anyone familiar with Symfony can use the url to delete stuff from your database.

I am willing to bet the problem is with your link that goes to the delete url. In your template, if you create a basic HTML link/anchor like this:

<a href="www.mysite.com/frontend_dev.php/picture/delete/id/1>click me</a>

Then a _csrf_token is not generated and is not being passed. But if you generate a link using Symfony's helpers like this:

<?php echo link_to('click me', 'picture/delete?id=1') ?>

Then the link will be generated along with some javascript that inserts a hidden input field called _csrf_token. This method will correctly pass the CSRF token to the delete action and you will be protecting yourself.

The CSRF protection is there to protect you. Learning how to use it properly is always better than commenting it out and disregarding it.

1
votes

You should use Symfony 1.4's built-in ability to generate a "Delete" link which uses JavaScript to perform a legitimate POST request to your delete route and passes along a valid CSRF token.

The following example assumes you have a route called file_delete which accepts a parameter id that is a number:

// apps/frontend/config/routing.yml
file_delete:
  url:   /file/:id/delete
  param: { module: file, action: delete }
  requirements:
    id: \d+

Generate a "Delete" link that properly does a POST and adds a CSRF token:

<?php
echo link_to('Delete', 'file_delete', array(
    'id' => $file->getId(),
), array(
    'method' => 'delete',
    'confirm' => 'Are you sure you want to delete this file?',
));
?>

While the above code works, I found a bug that still exists as of Symfony 1.4.18 that can result in the you seeing _csrf_token [Required.] after clicking the Delete link. This is due to Symfony generating JavaScript with a syntax error in it if passing an apostrophe into the confirm option (e.g. Are you sure you're ready to proceed?). To confirm the JavaScript syntax error is the culprit, open your browser's Console and click the link, then watch for an error to display quickly before it redirects. In my case it was easy to remove the apostrophe from the confirm text which fixed the issue.