I did work a part of the day on this project because I am making a new version of a Web site.
So what I did is...
First, create a table in a DB containing these fields :
id, parent id, user id, Type (is it a form or a field), Name (of the field), Alias (a strange string, randomly created), Broswer, IP, Minimum date, Expiry date
Then, when a page is loaded, it create a new key (which looks like this : bSg1VvBioT0cUgH31enpKxQJwiOMnWNJMRezc7tl3ZLSZRh, it his randomly created, it has a variable length, and it is unique in the db (some verification is made)).
Then, this key is inserted in the table like this :
Type=Form
Alias=(the key I just wrote)
Browser=$_SERVER['HTTP_USER_AGENT']
IP=$_SERVER['REMOTE_ADDR']
Minimum date=DATE_ADD(NOW(), INTERVAL x SECOND)
Expiry date=DATE_ADD(NOW(), INTERVAL y SECOND)
Then another key is created. It will be the first key alias, the secret key linked to it. Again, it looks like this : hpDVNJZ3711soTFNzoULcdTA92OeWa1AGOUYJ4a9
It is then inserted in the table...
[User id=(user's id if there's one)]
Parent id=(the id of the last insertion)
Type=Field
Name=Key
Alias=(the key I just wrote)
Browser=$_SERVER['HTTP_USER_AGENT']
IP=$_SERVER['REMOTE_ADDR']
Then, a hidden field is written after the <form> definition :
<input name="hpDVNJZ3711soTFNzoULcdTA92OeWa1AGOUYJ4a9" value="bSg1VvBioT0cUgH31enpKxQJwiOMnWNJMRezc7tl3ZLSZRh" type="hidden" />
Then, for every field needed in the form, the same process as the last insertion is used. The real name of the field will be stored under the Name field in the table, a unique key will be created, it will be stored under the Alias field, it will be linked with the form parent id (the first insertion id), also linked with the user id if there's one... The unique key (or Alias) will be the field name in the HTML.
When the form is submitted, the script receiving the form will first delete every row that have expired in the table (according to the expiry date field).
SELECT id FROM form_gestion WHERE Type='Form' AND Expiry_Date<NOW()
(let's say we fetch the resultats in $arrResults)
DELETE FROM form_gestion WHERE id=$arrResults['id']
DELETE FROM form_gestion WHERE Parent_id=$arrResults['id']
Then, it will retrieve all the rows (needed fields : parent id (as PID) and Alias (as Alias !) in the table where User id=user's id, Type=Field, Name=Key, Browser=(current broswer), IP=(current IP).
SELECT Parent_id, Alias FROM form_gestion WHERE Used_id=$intUser_ID AND Type='Field' AND Name='Key' Browser=$_SERVER['HTTP_USER_AGENT'] AND IP=$_SERVER['REMOTE_ADDR']
(let's say the results are linked to the variable $resResults)
For every result returned, it will check if $_REQUEST[Alias] is set (remember, that field contains the form's key contained in the Type=Form row).
If yes, it will check in the table if there is a form entry where the value of $_REQUEST[Alias] is the value of the Alias field (of course, Broswer and IP must be the same at the user's, and Type=Form, id=PID, also make sure to use mysql_real_escape_string() to avoir SQL injection). When selecting the result, something like this should be selected : NOW()>=Minimum_Date as Valid_Time (it will return if the minimum time has been reached).
If the number of resultats is one, we check if Valid_Time is 1 (true) or 0 (false). In case it is false, we display an error and make the script die, otherwise, we continue...
The script will retrieve all the fields where parent id = PID.
It will take the value of that field in the $REQUEST array, so something like $REQUEST[Alias], under it's original name stored under the Name field.
So $REQUEST[Name] = $REQUEST[Alias]
Then, it unsets the Alias key : unset($_REQUEST[Alias])
And then, the script can normally works !
I know, that's quite complicated, but ask questions if you don't understand !
I can't copy my script since it makes reference to included functions AND it's in French !