views:

70

answers:

4

I'm using jQuery in an app which registers user clicks to perform a given action through the .click() binding, and I want this functionality to be available only through a user mousedown. One of my friends pointed out today that it's possible to run $(element).click() from a javascript terminal in Firebug (or something similar), and achieve the same functionality as clicking on the element -- something I'd like to prevent. Any ideas on how to go about doing this? Thanks for your input.

+1  A: 

What are you trying to prevent? Someone messing with your client side script? You can do things like obfuscate your code but not much other than that. But even doing this is just making it more hassle than it's worth in my opinion.

If you don't want people doing certain things move the functionality to the server.

Sorry to be bearer of bad news.

spinon
Obfuscation seems like a terrible way to prevent your user from messing with their own javascript. If somebody really wants to go through all the trouble of making something work, then why not let them?
helixed
@helixed I agree .I said it was not worth the hassle but it is an option. I told him to move it to server.
spinon
Good point fellows, but my concern is not that someone *can* call it themselves, but rather that they could script it into something that could run very frequently. I need the event to only happen at the frequency of a human clicking a mouse. (and yeah, it communicates with my server on each call.)
Matt Nichols
+10  A: 

Short answer: No, you can't really prevent it.

Long answer: Any event like a click event is bound to such called Event handlers. Those handlers are functions which are executed when a given event occurs. So if you click on an element, your browser checks if any event handlers are bound to it, if so it fires them. If not, the browser will try to bubble up the event to the parent elements, again checks if there are any event handlers bound for that kind of event .. and so forth.

jQuerys .trigger() method (which is what you actually call if calling .click() for instance) just does the same thing. It calls the event handlers which are bound to a specific element, for a specific event.

EDIT

There might some simple ways to somekind of soft detect a real click, for instance you might check for the toElement property within an event object. That property is not set when triggered. But then again, you can easily fake that aswell with .trigger(). Example:

$(document).ready(function() {
  $('#invalid2').bind('click', function(e){
      alert('click\nevent.target: ' + e.toElement.id);
      console.log(e);
  });

  $('#invalid1').bind('click', function(){
      $('#invalid2').trigger({
          type: 'click',
          toElement: {id: 'Fake'}
      });
  });
});​

Working example: http://www.jsfiddle.net/v4wkv/1/

If you would just call $('#invalid2').trigger('click') the toElement property would not be there and therefore fail. But as you can see, you can add like anything into the event object.

jAndy
+1 very good answer, and I completely agree.
Rook
Makes sense. At least I can use your technique for "invalid2" in your example to make it a little more difficult to spoof. Thanks so much for the great answer.
Matt Nichols
+1  A: 

You cannot really do anything against it, it would also be possible to write the complete function and then fire it.

But why is this a problem? If somebody is changing something client side it only affects him. Or are you trying to check some data? This MUST always be done in the backend, because you can never be sure what is really sent to it.

TheCandyMan666
A: 

You can check event object (which is passed as first argument to handler) originalEvent. It will be undefined if event is simulated by .click()

But it's completely useless. You cannot use javascript for security - client has full control over it (and firebug console is just most obvious tool). Client-side security checks should be only hint for user and protection against errors, malicious input can be stopped on server-side only.

ymv