Smart way to generate a FORM key with PHP - php

I have a form, in whmcs that I want user to only be able to submit once, so they cant submit it and refresh to resubmit... I was thinking about unsetting $_POST or redirecting, but neither would work in this situation, how would I generate a key and make it so its only usable once? Can't use mysql.

Why not store a random key in the session? That's how most CRSF token systems work: When loading the form, generate the key and save it in the session and include it in the form. When submitting, compare the keys and delete the saved key.
If you just don't want the user to accidentally resubmit a successfully submitted form, the link from #zerkms' comment is what you want: http://en.wikipedia.org/wiki/Post/Redirect/Get

The most common way to avoid double-posting is to do
header('location: /'.$your_url_here);
after you complete your actions. So you just redirect to the same page, but without $_POST.

Set a session or cookie when the form has been submitted and check if it exists beforehand.
You could also store information in a database such as their IP and browser if you wanted a permanent check, but this has it's own problems so your never going to stop someone 100% of the time.

I realize this is an old question but I recently had the same problem. None of the Post/Redirect/Get solutions appear to work on WHMCS if you want to stay on the productdetails page (for example) even if you are switching to another smarty template file after POST. Probably because it needs $_POST[id'] and that goes away after a refresh. So the closest I could get was having it go back to the products list page which is not what I want and probably not what the original poster wants.
The solution I finally came up with was to add a $_SESSION[submitted] variable after the form was submitted. You will have to figure out the logic yourself depending on what you are doing.
My Logic goes something like:
if ($_SESSION['submitted'] == 1 && !isset($_POST['somecustomkey'])) {
unset($_SESSION['submitted']);
}
That is at the top and resets the "submitted" session key if your POST form data does not exist.
Then add a check before you write the info to your database or whatever.
if ($_SESSION['submitted'] != 1) {
//Do some stuff with $_POST form data
$_SESSION['submitted'] = 1;
}
I think this fits in well with the intended purpose of $_SESSION and easy to implement.

Related

preventing users from submitting data from form to mysql twice

I have a form where a user submits data from various text fields on my webpage to mysql database. Is there any code I can use were it will not let them submit/update the data again? e.g it will redirect them to a page saying sorry wwe have already received your data.
I have a unique number for each user if this helps. any help is appreciated.
Use tokens, it will avoid double submits and CSRFs.
Simply add tokens to an array, $_session most likely, and pop them when used.
Also, disable the submit button with JS after a submit.
You can also set a var in the session user that says he already performed an action, exampled uploaded his picture. Unset it if there is an error in your upload script for instance.
When you receive the post, query the database for the unique user number. If you get back a non-empty result, then display the error. Otherwise, save the data to the database.
The biggest thing you need to determine is what your unique identifier will be. It sounds as though you already have one (you mentioned unique user number?) Your unique identifier could be an email address, or even the full set of submitted data.
There are other ways to emulate this, such as setting a cookie on the user's machine, or disabling the submit button, but, none of these are completely under your control. The user could easily get past them if they tried. Therefore, determining a unique identifier and validating server side is probably the best way to do it.
The answer hugely depends on the reason for which user might send the data twice.
in case of an accident, there is one technique, and all other won't help you even a bit.
in case of intentional duplication the technique is completely different and again there is no general solution - everything depends on the certain scenario.
If you care to explain your certain case, you will get a proper solution.
For the most silly case of pressing "Reload" on a page with post results, you have to redirect browser using Location: HTTP header, e.g.
header("Location: ".$_SERVER['REQUEST_URI']);
exit;

Does this protect me against page reload and the back button?

Further to my previous question, here's what I decided to implement; it may not be pure P-R-G, but it seems ok. Care to comment?
The form.php has an action; let's call it validate.php.
validate.php is never seen by the user; if validates all $_GET and, if valid writes it to database and generates the HTML of a confirmation page / if not valid, it generates the HTML of an error page explaining what is wrong.
Whichever HTML is generated get stored in a $_SESSION variable and then validate.php does a header('Location: <as appropriate>);
Finally a page called submitted.php of invalid_input.php (in case the user reads the URL) consists only of echo $_SESSION['form_html'];
That seems to me like is proff against both page reload and back button problems.
Or did I goof by trying to reinvent the wheel?
Firstly, you're better off storing the form data, which means you can perform the validation again. It will also be less html. The problem with the method you're employing now is that it doesn't protect against multiple tabs, since $_SESSION is universal to a browser session.
One way I've used to prevent against duplicate submission (without PRG) is to generate a unique id for every page load (where a form is involved). When I generate that unique id, I add it to a $_SESSION['form_unique_ids'] array, and I include it as a hidden field in every form I generate. Then before I take action on a form submission, I check to see if that unique id is in the session. If it is, this is the first time that form has been submitted, and I remove it from the session. That way if I try to resubmit that page, I will know because that id is not in the session not to process the results.
This could be extended so that instead of storing a single id, you use the id as the key in the array, and let the value be the result of the transaction. Then:
If there are errors, you store the $_POST data as well. Then, redirect to original_form.php?id=unique_id and display the validation results. You can either store them or recalculate them there.
If there is success, store the success message and redirect to success_page.php?id=unique_id. Display the success message prominently there. If you like, you can remove it from the page.
You have the option of removing the session data when you display it, but that would mean if they refreshed the edit page they'd lose the validation messages and saved form data. I'd rather find a way to get rid of data that is old enough that they're not likely to need it anymore.
Anyway, some of those ideas might be useful. Then again, maybe it's way too much effort for the problem. Your call :)
As long as you use a php redirect at the end of your validate you cannot reload or back button into the validate.php

How do I control flow of PHP multi-page form?

I am a bit of a PHP newb
I have developed a multi-page form which works fine at the moment - each stage is on another page (I use the session to retain the data).
However I know that users don't always use these forms the way you want!
I want to control the flow of the form.
I would like the user to be able to use the browser back & forward button for ease of use.
They should not be able to skip a part of the form by entering a form stage URL directly into the address bar to get the a later stage in the form (essentially skipping a part of the form).
The form also does not flow the same path every time, it is dependant on the users choices what stage is displayed next.
I was wondering if anyone had any ideas of ways to control the flow of this multi-page form thank you!
store form results in SESSIONS (encrypt them if sensitive)
then just check on each form if the value is set and show it as necessary.
use another session to check the "progress" of the form, to prevent the user from skipping ahead.
for example...
<?php
/* on form 3 */
if(isset($_SESSION['progress'] && $_SESSION['progress']==2)
{
//the second form has been filled out and validates
}
else
{
// the 2nd form hasn't been finished, redirect
}
?>
you could also use like a percentage based system in the session - a value of 90 means that 90% of the form fields have been completed - for displaying "progress" in a visual means to the user.
basically on every form submission, check whats been submitted, if its expected, then set appropiate sessions to redirect to the next stage.
check every set session on every form to determine if the user should be here yet.
Push the data for the non-current fields into a hidden field in the browser (to save time and effort - just serialize an array/object).
I would like the user to be able to use the browser back & forward button
If users are allowed to re-enter previous stages, just let them and rewrite current stage in the session.
If not, make form fields read-only and do not process submitted forms for the previous stages.
That's the only problem I can see here.
You can either use session data to retain the state between multiple pages, or you can transfer all data on each page. Typically you would do the latter with hidden fields or you will create one humonguous form, and use javascript to make it appear as if it was multiple pages, when - in fact - it's not.
There are pros and cons to each solution.

Making form submissions unique using PHP and HTML

I'm currently developing a page where the user fills out a form, and when submitted they are taken to the next page. When on the next page, I want to have it so that if the user went back to the previous page using the back button, or hit refresh, the submission will not be saved into the DB.
Now I recall reading somewhere that if you had a way to make each submission unique, this issue is averted, but after screwing around for hours on end, for the life of me I cannot recall how this could be done (using PHP), so long story short has anyone ran into this, and if so, what was your solution?
Use the Post/Redirect/Get pattern to avoid this problem. See also Redirect After Post.
Another way is to generate an identifier using uniqid and include it in the form as a hidden input. On submission, store that identifier in a database column marked with a UNIQUE index. This will cause subsequent submissions to throw a SQL error, which your application can handle gracefully.
You can add any confirmation on the second page.
By adding any confirmation box or any button....
by which you can confirm that whether user want to save it or not....
and if you don't want any confirmation...then you can delete the last record....by using managing session...but it is not good practice to fire the query very soon and delete in that kind..
so best way will be by adding any confirmation msg....

How do you recommend I pass data from one form to another, and finally to another final page?

I'm taking a class in PHP and I'm a real newbie when it comes to best practices and whatnot.
I have a little homework that the teachers wants me to hand in.
Create a form that asks a user for his name, last name, age and birthday.
When the users clicks submit, take him to the second form and ask for his location, nationality and religion.
Finally when he submits that, take him to a 'thank you' page showing all the written information he input previously.
I'm thinking about using GET to pass things along, but I've only done this with one form to another, not multiple 'hops'. Would this work?
What other way do you think I should do this? I'm not sure if this should be community wiki because I'm sure there's a perfect answer, but please let me know and I'll change it.
Thank you SO. :)
You need sessions. Sessions store an ID on the computer, (sometimes in a cookie) that references information on the server. You just create a session, and then you can put whatever data you want in it. Just grab that data on another page whenever you want.
page 1
session_start(); // start session
$_SESSION['name'] = 'Jimmy'; // put something into the session
And on the next page...
echo $_SESSION['name']; // echos "Jimmy"
session_destroy(); // don't want the session anymore
More info at http://w3schools.com/php/php_sessions.asp
Use session.. Make sure you clear it when you are done saving the data.
when rendering the second form you could include all the fields from the previous form as hidden fields.

Categories