I've a php web page with a form. After filling the form in web page, I can submit it to the server. But after that, if I refresh the page, it inserts the same record to the database. Is there any solutions to this problem?
Use the POST/Redirect/GET pattern. This will prevent the user from being able to resubmit the same form.
There are a number of ways, for example:
Create a token which you insert into the form (hidden field). if the same token is submitted twice, discard the second submit.
Check in the database if an identical post already exists.
Save the form submit in a session variable.
Redirect the user to a second page after the submit, using the Post/Redirect/Get pattern (preferably in combination with one of the above).
Yep, do two queries. The first checks to make sure the data doesn't already exist in the DB, the second one does the insert if there is no duplicate data. There are a bunch of ways to go about checking to make sure the duplicate data doesn't exist, but this is the basic process you will want to go through.
Well, that's what Refresh means: "do it again."
You can check to see if data that matches the submitted data is already in the database. If so, you can reject the new submission.
Before inserting to the database check whether the same values are duplicates already, and if they are duplicates, don't insert. Checking for multiple columns helps even further. For example, instead of checking just for a "username", you would check for a "username" AND "password".
Obviously the examples above are fake, but you should get the point.
You can make a process.php page and set your form's action to it.
In process.php
//code to insert item to database
header('Location: YOUR_FORM_PAGE_HERE);
Then it will send them back to the original page and there won't be any post data
You could change your query to INSERT IGNORE INTO table_name ...
this will prevent you from inserting twice.
Related
I'm trying to write an app that basically is a frontend for editing database records. I have heard that a way to ensure the right row in the DB is being updated is to include a hidden form field on the update form with the row unique ID in it, and use this to add a conditional to the backend update statement.
However, this seems insecure. Anybody could edit the HTML on the page pre-submit and change the record being updated, no? What is the proper way to pass the unique ID of the row the user is editing along with their edits? I would imagine this may be done with cookies/session tracking, but couldn't this be edited client side prior to submitting as well?
Thanks!
If a client is allowed to modify the record in question anyway, it doesn't matter whether he does so by modifying the id in a hidden field or by going to the correct page and submitting the form from there.
When any client submits any form, the server needs to a) make sure the client has the right to modify the record he attempts to modify and b) validate that the submitted data is allowable for the record. Then all your business rules are being protected and taken care of, whether the user uses the proper forms or not.
You can also save a hash of all hidden fields in the session server-side and check that on submission to catch hidden field-manipulation attempts, if that's still in your interest.
You may create a field with default value TIMESTAMP.
Also you may pass this data from one page to another using php sessions
More details here
Hope this helps.. :)
When you load the form page, store the id in the session however you want to.
When they submit, on the post page, grab the id from the session.
The insecure part is, how are you letting people decide which id they want to edit? Where is the input for that?
I am new to PHP, so I am looking for some input on how to make my project a little simpler.
I have a form in which a user can create a list of song, the Submit button then sends it to an intermediate page that saves it to a MySQL database for later use, the intermediate page then forwards them on to the final page that shows them the lyrics of the songs in the order that they chose them.
Originally I had the intermediate page and the final page combined, but ever time a user refreshed the page it would resubmit the data to the DB. What I have works, but it seems like there should be an easier way to accomplish this.
#micahmills: An easier way of stopping duplicate data from being added to the database? Well, it would depend on what you'd consider "easier" -- less code? Less steps? Something else?
What you could do is generate a unique hash or token that submits with the form. This token is then stored in a session after successfully inserting to the database. Attempts to repost the form will then fail because the token sent with the form will be the same as the one stored in the session.
Redirecting to another page after posting to the database is still one of the best and simplest ways of preventing duplicate data being posted though.
Best practice is to redirect after database operation to success / failure page.
You can have form & intermediate combined and a final success page, on failure you need to return back form.
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
On my site, I have a form that users fill out to become a member. They fill out name, bday, email, etc. Then when they click submit, the data gets into mySQL. But sometimes when a user clicks submit many times or refreshes the page, the data gets inputted to the database more than once. How can I prevent this accidental submission? Is there a code I can use to only let one set of data get into the database?
This is also a problem in my comment section. I allow uses to put comments on people's profiles. But when they abuse the refresh button or submit button, I get like 10 of the same comments. I am trying to prevent users accidentally submitting a comment twice.
Thanks.
Create a UNIQUE constraint:
CREATE UNIQUE INDEX name_of_youw_index ON tablename(columnname);
INSERTs will now fail with double data.
In the first case you probably just want to add a unique index on the email address and use that to create a profile for that user.
In the second case, as I understand it, you are trying to prevent users from accidentally submitting data twice, not to completely prevent data being submitted twice. You probably don't want to prevent people from writing the same comment twice on the same page. If someone writes "Today was like yesterday!", you don't want to prevent them from coming back the next day and writing "Today was like yesterday!" again. This would be unnatural and the check could be expensive as it would require indexing a lot of data. I think you want to prevent someone from submitting the same form twice, regardless of whether the data is the same or not.
So the solution to your second example is to include a hidden field in your form that uniquely identifies it. When they submit the form, mark the value in the hidden field as used. If someone later submits a form with the same value in the hidden field, reject it.
Server-side: Implement throttling. Only allow 1 submission every 10 seconds or so.
Update: When you accept a form submission, record the timestamp you
made the submission in $_SESSION.
When you accept another (or rather,
every) form submission, check if the
value stored in $_SESSION is older
than 10 seconds. If it is, continue.
If it isn't, don't do any more work.
You could do it with just some
database stuff to I guess, but
$_SESSION is much simpler.
Client-side: Disable the submit button via Javascript when the form is submitted.
Make the email field in your database "unique", by adding a unique index to it.
If your database gets another entry with an email which has already been used then mysql throws an error - the error number is 1062.
If you wanted to then you could handle this error different from others.
mysql_errno()
http://www.php.net/manual/en/function.mysql-errno.php
In the case of the database duplicates, put a unique constraint on the field.
For both the database duplicates and the duplicate comments, disable the submit button for 2-3 seconds after it is pressed to prevent multiple submits.
I want to ask a best practice question.
Suppose I have a form in php with 3 fields say name, email and comment.
I submit the form via POST. In PHP I try and insert the date into the database.
Suppose the insertion fails.
I should now show the user an error and display the form filled in with the data he previously inserted so he can correct his error. Showing the form in it's initial state won't do.
So I display the form and the 3 fields are now filled in from PHP with echo or such. Now if I click refresh I get a message saying "Are you sure you want to resend information?".
OK.
Suppose after I insert the data I don't carry on but I redirect to the same page but with the necessary parameters in the query string. This makes the message go away but I have to carry 3 parameters in the query string.
So my question is:
How is it better to do this? I want to not carry around lots of parameters in the query string but also not get that error. How can this be done? Should I use cookies to store the form information.
Your first scenario seems the most valid.
i.e.
User submits the form
Some problem prevents submission, so form is re-displayed
If user "refreshes" they see the usual message about re-sending information (although their most likely path of progression is to re-submit the form that you are kindly re-populating for them).
The "Are you sure you want to resend information?" message is perfectly valid in the event of someone refreshing the page after a form submission, so don't write code to specifically break this behaviour.
I think generally people would temporarily store the submitted data in a session variable, and send the data back to the client.
Maybe it is besides the point but you mentioned "wrong dates", and I think many would say you should arrange things so that the user cannot unintentionally send you wrong dates.