Preventing form_token from rendering in Drupal “GET” forms

梦想与她 提交于 2019-12-03 06:43:56

Yes, there is a way, but use it consciously (see warning below):

If you create the form yourself, adding

$form['#token'] = FALSE;

to the form definition array should prevent a token from being generated in the first place.

If you are dealing with an existing form, you can bypass the token validation process by unsetting the '#token' element on hook_form_alter:

// Example for removal of token validation from login (NOTE: BAD IDEA!)
function yourmodule_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'user_login_block') {
    unset($form['#token']);
  }
}

Warning: Given your question, I think there is a slight misconception concerning the difference (better, the lack of a difference) between GET and POST requests.

... on forms using the "GET" method shouldn't need this token. All it does is lengthen and uglify the resulting URL.

This is wrong! GET and POST are just two different, but mostly equivalent methods of transmitting data from the client to the server. Since POST is better suited to transfer large amounts of data (or difficult formatted data), it is the established standard for submitting forms, but it is in no way safer/unsafer or more/less secure than GET requests. Both type of requests can be tampered with by malicious users in the same ways, hence both types should use the same protection mechanisms.

With a GET request, the token does exactly the same as with a POST request - it proves to the server that the submitted data comes from the same Browser on the same machine as the request he build the form for! So you should only remove it if you are sure that the request can not be misused via XSRF.

Trevor McKeown

This worked for me. I had to unset all the form api elements and set the #token property to false. Notice the after_build function for unsetting the other properties.

   function mymodule_form(&$form_state){
      $form['name'] = array(
        '#type'   => 'textfield',
        '#title'  => 'name',
        '#value'  => 'name', 
      );
      $form['#method'] = 'get';
      $form['#action'] = url('someurl');
      $form['submit'] = array('#type' => 'submit', '#value' => 'go');
      $form['#token'] = false;
      $form['#after_build'] = array('mymodule_unset_default_form_elements');
      return $form;
    }

    function mymodule_unset_default_form_elements($form){
      unset($form['#build_id'], $form['form_build_id'], $form['form_id']);
      return $form;
    }

The site I work on uses the Drupal 6 form API for custom search forms, so by removing the token and build id we were able to cache the results in memcache. Now we've moved to Acquia hosting, it's cached using Varnish.

To remove the form_token and form_build_id from your form and submit it as a GET request, use the following method:

<?php

function module_example_form($form_state, $form_id = NULL) {
  // Form root settings.
  $form = array();

  // Set the submission callback for this form. 
  $form['#submit'][] = __FUNCTION__ . '_submit';

  // Set the request method for this form to GET instead of the default
  // of POST.
  $form['#method'] = 'get';

  // Remove unique form token so request can be cached. This is accompanied by
  // code in hook_form_alter to ignore the token and remove the build_id.
  $form['#token'] = FALSE;

  // Submit button.
  $form['go'] = array(
    '#type' => 'submit',
    '#value' => t('Go!'),
  );

  return $form;
}

/**
 * Implements hook_form_alter().
 */
function module_form_alter(&$form, $form_state, $form_id) {
  // Changes to the 'module_example_form' form.
  if ($form_id == 'module_example_form') {
    // Unset the hidden token field and form_build_id field.
    unset($form['#token'], $form['form_build_id'], $form['#build_id']);
  }
}

?>

I find that simply throwing away the CSRF token is not an option. We solved it using hook_theme_registry_alter() to overwrite the Drupal core theme_hidden() function so that the hidden form element 'form_token' is rendered as an <esi /> tag. The tag will cause Varnish to make a call to a PHP file which we allow to pass through the cache. This file will calculate the proper form token for the current user and will then output the HTML code for the hidden field. You can calculate this token without a Drupal bootstrap, but you will need a single DB query to fetch the *drupal_private_key* for your site, which is stored in the variable table.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!