views:

612

answers:

1

What is the difference between using:

$.ajax({ type: 'POST', url: Drupal.settings.basePath + 'module/get/' + node, dataType: 'json', data: { 'ajax' : true } });

versus:

$.ajax({ type: 'POST', url: Drupal.settings.basePath + 'module/get', dataType: 'json', data: { 'ajax' : true, 'node' : node } });

In the first case you'd access the node variable as a parameter in the callback function and in the second case you'd access it with $_POST['node'] right? Wouldn't the second method always be better, but I see a lot of people doing it the first way. Not to say that the second way is that secure either. Still looking into form tokens, but trying to figure out this basic bit first.

Also wondering for case 1, assuming this ajax is triggered by a button, how do you stop a person from entering directly into the url, mysite/module/get/20 and activating it? Does simply checking that $_POST['ajax'] == true do that? Or is there still a security hole there?

+2  A: 

No real difference at first sight:

Assuming that your 'node' variable is just a node id, there is not much difference between the two. Semantically, both seem to perform a 'get' operation (even though they are technically post requests), as they just retrieve data without changing any state on the server (ok, that's another assumption).

Security wise, there is no relevant difference either - both can be 'forged' easily and the difference boils down to the same as with the 'standard' GET vs. POST debate, that is, no difference except that the first exposes the parameters a wee bit more 'accessible' to the casual observer, as they are in plain sight within the URL.

But a 'convenience' difference within Drupal:

Within Drupal, the first version is often encountered because it can make use of the Wildcard Loader Arguments functionality (introduced in Drupal 6). Let's say your callback URL is defined in hook_menu like so:

$items['module/get/%node'] = array(
'title' => 'Foo',
'type' => MENU_CALLBACK,
'page callback' => 'yourModule_callback',
'page arguments' => array(2),
);

With this, yourModule_callback() will be called with its first parameter already being the fully loaded node obect for the passed in nid, as %node tells Drupal to execute a node_load() on the parameter before handing it over to the callback function. Using the second version of your example, the callback function would have to load the node object itself, after extracting it from the POST data.

So a convenience thing here.

Additionally, a common pattern within Drupal is to use the same callback URL for an AJAX request as for its non javascript 'fallback' alternative. So when yourModule_callback() is invoked, it can do whatever it is intended to do with the passed in node first, basically assembling its result. After that is done, it only checks for $ajax == TRUE within the POST data. If it is there, it knows that the result is intended for an AJAX request, so it might output the result as a JSON. If it is not there, it knows that a full page cycle is going on, and can adjust its output accordingly (e.g. rebuilding a form, regenerating a whole page, whatever ...).

That way, you don't have to register separate URLs for your non AJAX/AJAX callbacks.

Henrik Opel
Thanks for explaining the difference between the two in detail. :) I see how both ways can be useful now. The way my form works is that it is generally intended for ajax, but if js is disabled, it will fallback to submitting the form with the form api.
Wade
Wade
It would not be 'foolproof'. It would only confirm that 'ajax = true' got posted to you, but not that this post actually came from your form. (Thus only preventing the 'easy' access via a standard GET). To ensure that the post itself came from the form, you have to use the formsAPI processing logic to rebuild the form and verify the form Token. This sounds like overkill for a simple AJAX callback - why are you concerned that someone can get the data without coming from the form? (If a user can access the form, ha can get at the AJAX response anyways)
Henrik Opel
For this ajax I'm not too concerned, but I also have another ajax form that inserts the data into the database. I have just added an additional token to my form, but I'm not sure if its the same kind you mentioned. I used drupal_get_token to add it to the drupal.settings and send it as data and use drupal_valid_token to verify on server side. That is to prevent XSS and the token your talking about is different right? How would I use that method? Maybe that would also help my other question: http://stackoverflow.com/questions/2130714/drupal-6-validation-for-form-callback-function
Wade
That is the same token mechanism used by the forms API. I posted an answer to you other question - the links in there should help. (Sorry for not posting a concrete example, but I do not remember the details from the top of my head and always need to look up this stuff again myself after a couple of month ;)
Henrik Opel