views:

199

answers:

4

I noticed that for voting SO implements an XHR method which POSTs to a posts controller and sends the post ID and vote type through the URL, in addition a fkey parameter is sent, eg:

http://stackoverflow.com/posts/1/vote/2

I'm going to be implementing a similar technique, I'm wondering what logic I could use to prevent duplicate voting by the same user and prevent spamming, in addition to overall logic when implementing this.

The schema for the table I'll be storing them:

thread_id   user_id   vote_type
2334        1         2

So far I came up with these bullet points:

  • ensure the user is logged in
  • ensure that a valid post ID and valid vote type is sent
  • ensure that after POSTing, the user has not previously voted
  • the code that creates the hash can't contain dynamic information such as user agent, since a user could be on a different browser, different OS, right?

Update:

"SO is probably using the login cookie to identify the user." - Andrew

Could someone demonstrate how this would be done, or in other words more specifically provide an example of how the fkey, which is an alphanumeric 32-bit string, is generated?

Question:

  • since I'm not sending the actual user id anywhere with my XHR code, does this mean I have to update my table schema so that I can store the fkey instead of say, the user_id? The fkey will probably have to be unique to each user, and so I can probably query whether there is a row in the voting table that has an fkey of whatever.

Would appreciate any tips or insight on anyone who's implemented a similar technique.

+1  A: 

You can just sign the URIs somehow in order to prevent users from manipulating valuse. For instance, you could hash parts of the URI with a secret and append the hash to the URI. When users copy the URI and change values, the URI and the signed part become invalid.

This is often done in RESTful APIs, and your current approach is similar to.

PartlyCloudy
+1  A: 

I think it depends on how badly you want to keep people from re-submitting or fiddling with your data. Nothing will be 100% (unless your budget is through the roof), but you can do a good job of keeping most people from resubmitting by:

  • check their UID - or generated ID from the UID (I will explain)
  • record their IP address, and check against the DB for the IP and the submission ID (along with the generated UID)

Using the IP solution alone, can be defeated by using a proxy of course, or a connection that changes IP's often such as the DSL carrier in my city (but even then, its every couple of days). I personally generate a unique key based on that persons UID, and pass that back and fourth if necessary. A salted MD5 hash usually works fine, or even an AES implementation if MD5 is viewed as too weak. Combined together, you should have a good starting place.

Liam
can you include examples of md5 plus a salt in this context, along with the user id?
meder
$new_uid = MD5($user_name."this is my salt");with $new_uid, you can store this value into the database that will be unique to each member. Of course I am assuming that each member already has a unique ID such as an email address that this is based off of (for $user_name).You can then perform a query against their ip - $ip = $_SERVER['REMOTE_ADDR'];and the unique ID generated with the salted MD5 hash. Its not perfect, but a base to work off of.
Liam
+2  A: 

create UNIQUE index on fields (thread_id, user_id) and DBengine will protect you from multy comments on one thread :)

SM
A: 

Hey meder this is John get back to me ASAP via aim! I've been trying to reach you for the past one week.

John