I recently created a website that has a voting/upvoting feature that uses jQuery’s AJAX functions. The catch is: anyone can vote. I don’t require visitors to be logged in, I don’t track their IP, and I don’t even store a long-term cookie. Normally (don’t laugh), when a user votes on something, I store the ID of the item they vote for in a JavaScript array. Whenever they try to vote, the script checks if they have voted for the given item recently by checking the array for the ID. If they have, it just gives them an alert dialog. Otherwise, it casts a vote. So it goes without saying that all a user has to do to vote again is refresh the page.
I decided to see what happens if I injected some JavaScript (in the URL bar or a web console), and I wasn’t really surprised to find out that voting as many times as you want very rapidly is as easy as:
for (var i = 0; i < 100; i++) { vote(itemID); }
(and that’s being nice). I’m not sure why the array isn’t stopping it, but that doesn’t matter; it will always be easy to exploit this, right? I mean – you could even write a little HTML document with some JS that calls the voting page on my website as many times as you want.
So I want to fix this without too much trouble. Is it possible to create an immutable variable in JavaScript? A constant (though it would really help if there was such thing as a constant that could be changed only once)? The easiest way to fix this to some degree would be to keep the ID-holding array semi-constant: can’t be deleted, but can be added to. Any suggestions or solutions or explanations are greatly appreciated.
No, if the users want to cheat by messing with their client-side code, they can do that. This is just like cheat patches for games.
What you are doing now is very reasonable to avoid accidental duplicate votes, if you feel that this is not enough (for example if the votes are really important), you need to take measures on the server-side. Tracking IP or setting cookies also won’t work, this relies on client-side cooperation as well. You’d have to authenticate the users and mave sure everyone votes only once by storing something in your database.