I have a main form with a lot of inputs. The forms action is set to a php file.
After submitted the php-page shows up with all the inputs that the user typed into the form. The user has to re-check everything and hit an 'approve' button!
The problem is, I don't know how to do this...
I want to eventually put all data into a MySQL database, but only after hitting approve, not submitting the form!
Is there a way to 'recall' the php script after clicking the button 'approve'?
How is this done? I mean, I don't want to write information to the MySQL database, and then the user regrets and DOESN'T hit 'approve' and then the data is already in the database.
Thanks!
Just let me know if you need more input (I will then update the question)
One way to accomplish this is rewrite every value that was just submitted into the approval form in the form of html hidden inputs. Like this:
<form name="approval" method="post>
<input type="hidden" name="firstname" value="<?php echo htmlspecialchars($_REQUEST['firstname']); ?>" />
<input type="hidden" name="lastname" value="<?php echo htmlspecialchars($_REQUEST['lastname']); ?>" />
...
<input type="submit" value="Approve!" />
</form>
Others have suggested storing the values in the users session. If you choose to go that route, be careful about user's who like to work with multiple browser windows open at the same time. Their different forms will share the same session and depending on what order they choose to submit forms in, you could end up with some crossed wires if your code is too naive. One way around this is to generate a unique key for each form and pass it around from page to page. This of course gets messy which is why I prefer the hidden form field approach.
Another pitfall related to the session approach is the PHP's default session implementation uses the local filesystem to store session data. This breaks down when you have redundant web servers. You can, of course swap the default file based session implementation for something more sophisticated (based on memcached perhaps). But again, this is just more complexity. Why not avoid the complexity and stick with hidden form fields?
You can store the information in one of two ways: using the session or as hidden form inputs.
Using a Session It would make a lot of sense to use the session in this case. So, when the first form is submitted, start a session with the user and save all the values in it. Then, the confirmation page simply shows the data. When the user hits "approve", this triggers your script to store the information that is already in the session. This is a well-known method for persisting information between requests.
Using a Hidden Form As you write out your "approve" page, you could also write hidden form inputs along with your displayed confirmation data. Adding a new field to indicate that the user has approved this data, your script will only write to the database when it sees this confirmation value.
Without knowing much more about your application, I'd prefer using sessions in this case.
You could store all the information in a session first. Then make your calculations, and have the user approve the information. Write them from the session into the database.
Related
I am currently having an issue with using a nonce as a security solution in PHP
i read this post about
How to check if a request if coming from the same server or different server?
about using an hidden input form field to hash a random value and At the same time, store that random value into the session that correspond to the user.
When the form is submitted, check that the hidden field has the same value as the one that's stored in session. (I think am having a problem with this)
Example
<?
$_SESSION['formhash'] = md5('any value to be hashed');
?>
<input type="hidden" name="hashed" id="hashed" value="<?php echo $_SESSION['formhash']; ?>" />
A user having an Mozilla Firebug and inspecting the element will still find out my hidden field and then copy it. And then create his/her own form then post it to my url and the Login will still be Bypassed.
Image showing example
Is there any more secure way to do this ?
Any help will be appreciated thanks !
The bottom line is that you cannot prevent a user from manipulating the form data prior to submitting the form. What your solution does is confirms that the form data is coming from the user you sent it to.
Regardless of whether or not a user is "logged in", you will probably start a session each time a new visitor hits your site. This means you can store the hash value each time you send them a form and you should, in theory, be able to associate the hash value on the returned form data with the hash value in the session (just like your code is doing).
Armed with that knowledge, we can consider the following scenarios:
The typical use case is that a user submits a form without modifying the data. Your approach will allow you to confirm that the form has been posted by that very user. Your validation code should confirm that the POST data is acceptable.
If a user modifies the form data and submits it, your approach will allow you to confirm that the form has been posted by that user, but not that the form has been messed with. This is why you need to validate forms very, very carefully.
If a user grabs a form that was actually sent to someone else and posts it - modified or not - your system will allow you to confirm that the form did not come from the user that it was originally sent to and you should reject it.
Scenario 3 is what is known as a CSRF attack and your solution is the standard defense against this attack.
PS As #cHao says, you should regenerate the hash for every form you generate.
I'm using hidden form to send value. With a submit button.
Its like:
<form action="users.php?action=edit" method="POST">
<input type="hidden" name="first_name" value="Josh" size="20" maxlength="19"/>
<input type="submit" name="done" value="Done"/>
</form>
And i'm using these values in the next form i'm creating. I don't know which will be better, doing it like this or by getting data from database. Also, which will be more secure ?
Speed is variable.
The more important question is what is safer: If you store the information on the form, it could be changed by a malicious user.
Never trust any data that comes from a web form - always check and verify it.
I remember one, possibly apocryphal, story about how an early web store stored their prices on a hidden field on a form, and were delighted with the level of sales, only to discover that those sales had been made at a much reduced price due to field meddling by devious consumers.
See http://www.ethicalhacker.net/content/view/43/2/
Getting data from database is more secure as the data cannot be tampered.
If you will put it in a hidden field it will display the value of the php variable which can be modified.
i guess it's getting data from the database
first people can manipulate datas and secound i guess your db is localhost or in the same network - that makes is faster then sending it over the internet and secure!
I guess "Josh" is the user to be edited and only the logged in "Josh" user can do that. If you would not hesitate to show the data in the hidden field to the user, you can use the hidden field.
Be aware that a user can tamper with the values in the form fields. Everything the user can add to/change in the HTTP request needs to be validated on your server (if it's a reasonable value, if the user actually has the right to edit "Josh" etc.)
In your example there is not really a reason to use the hidden field though:
<form action="users.php?action=edit&first_name=Josh" method="POST">
<input type="submit" name="done" value="Done"/>
</form>
About the speed: For little data, the hidden field version would probably be faster since you avoid a whole roundtrip to the database (Connecting, Transaction, Disconnecting). PHP does not keep a connection pool and connecting to a database is expensive.
I'm working on something that allows users to edit a form they've submitted and I have two questions.
Say I'm on page viewform.php and the page to edit the form is editform.php. Is it safe to pass the form's ID through the url and use then use GET. I'll verify the person trying to access it on editform.php is the person who created it using a session ID tied to the username , set upon logging in.
If 1 isn't a safe method, how can I POST that data (using a submit button I suppose) from viewform.php to editform.php?
If I understand your question correct, what you are looking for is how to persist data across requests using forms? Because then you can have a submit URL specified in the action attribute in the form, and you can access the values of the form from that URL through the Request Object. And for submitting your data to the same page, you can use $_SERVER['PHP_SELF'] which carries a reference to the page you are on. So, to answer your question, your viewform.php will have:
<form action="editform.php">
<input type="text" name="inputvariable" />
<input type="submit" value="Go" />
</form>
And in editform.php, you can access inputvariable's value by accessing $_REQUEST['inputvariable']
Hope this helps.
Sure, $_GET is safe as long as there isn't any sensitive data transferred. An ID is what is commonly used
Why not set the method of the submitting form to 'POST'. Using 'GET' could lead to someone modifying the URL of the page and inserting data that could have some undesired effects on your website.
If using POST, when receiving the data, set your variables as such
$var1 = $_POST['variable1'];
You can save the Id in the $_SESSION array then match the id you got from the url with the id you saved in the $_SESSION.If they does not match you can show an error message.This will prevent your site from behaving undesired way if anyone changes the url.
I have tried:
the POST/REDIRECT/GET method, but this does not protect against multiple instances of the same form (e.g. if a user opens form.php in two separate windows, and submits the form in window 1, they can still submit in window 2)
the UNIQUE TOKEN method, where a uid is generated into a session variable when the form is loaded and confirmed and unset when the form is processed, but if the user has other different forms open, the variable is unset from these other forms as well so they get treated as 'already processed'.
Have you seen the comment from user "Ofir Baruch"? It seems correct to me.
You just need to combine the two approaches you have already tried, make it correctly, and, as Ofir baruch said, have a unique token session for each form.
More or less like this:
form1.php
session_start();
if (empty($_SESSION['form_tokens']['form1']))
{
$_SESSION['form_tokens']['form1'] = generate_random_token();
}
if (isset($_POST['token']))
{
if ($_POST['token']) != $_SESSION['form_tokens']['form1'])
{
// the token is invalid - do not process the form
redirect('/some_page');
}
else
{
// process the form here
if ($success)
{
// reset the token for this form
unset($_SESSION['form_tokens']['form1']);
redirect('/another_page');
}
}
}
<form id="form1">
<input type="hidden" name="token" value="<?php echo $_SESSION['form_tokens']['form1']; ?>" />
<input type="submit" value="Submit" />
</form>
In form2.php you would do the same, but using its unique token instead:
$_SESSION['form_tokens']['form2']
If you want to prevent ALSO using two different browsers - or even computers - and this is so important, then you should deal with it at another place - I mean, you should not allow that a same USER can have TWO SESSIONS. There are several ways to accomplish this, but it is another question.
Are the form submissions limited to logged-in users or site visitors?
If this form is only for logged-in users, you can check their user_id as soon as the form reaches your controller. You could set a temporary cookie or session variable while the form processes. When the form completes, you can unset this session variable. As soon as the form submits, check to see whether this session variable is ALREADY set (i.e. whether or not they've sent the form twice). If this session variable is detected, fail the request.
I suppose you can do the same with site visitors, or even resort to using tables to store IP addresses, but that's a tad excessive and resource intensive.
Identify which forms you want single submissions only. Then add your unique token as hidden id, for each time you generate form html and store in session. This was you know all valid IDs that are part of the unprocessed group. just one submission cancels all other IDs too of that group ONLY. this also means, when he opens few other forms after that, they start creating new group.
this open needs you to have a session array (or db) with items of all IDs that belong to unprocessed form. only one group can remain at a time. any ID not in the group is ignored/cancelled.
I want to prevent users from accidentally posting a comment twice.
I use the PRG (post redirect get) method, so that I insert the data on another page then redirect the user back to the page which shows the comment. This allows users to refresh as many times as they want. However this doesn't work when the user goes back and clicks submit again or when they click submit 100 times really fast. I don't want 100 of the same comments.
I looked at related questions on SO and found that a token is best. But I am having trouble using it.
//makerandomtoken(20) returns a random 20 length char.
<form method="post" ... >
<input type="text" id="comments" name="comments" class="commentbox" /><br/>
<input type="hidden" name="_token" value="<?php echo $token=makerandomtoken(20); ?>" />
<input type="submit" value="submit" name="submit" />
</form>
if (isset($_POST['submit']) && !empty($comments))
{
$comments= mysqli_real_escape_string($dbc,trim($_POST['comments']));
//how do I make the if-statment to check if the token has been already set once?
if ( ____________){
//don't insert comment because already clicked submit
}
else{
//insert the comment into the database
}
}
So I have the token as a hidden value, but how do I use that to prevent multiple clicking of submit.
METHODS:
someone suggested using sessions. I would set the random token to $_SESSION['_token'] and check if that session token is equal to the $_POST['_token'], but how do I do that? When I tried, it still doesn't check
If you want to prevent double submissions, you must store the state of "is submitted" versus "is not submitted". You have several options for where to keep this information.
Database - Add an hidden field with an autogenerated value that is unique (you can generate a short random string it and append the current time). This value can also be used to identify the conversation -- if you need a stateful web conversation. Add this value to the database and make it unique. Disadvantages: redundant storage in the database, reduced performance on comment insert, have to generate a unique string.
Session - Add the same hidden field with a value generated in a similar matter. When the user submits the form, save the value in the session if it's not there already. If it is, it's a double submission. Disadvantages: you still need to generate the unique token.
Browser - (1) Add some javascript to disable the submit button once it's clicked. (2) have an hidden field that starts with the value 0 and is changed to 1 when the user clicks the submit button. If the user clicks the button again, you check whether the value is 1 and abort if it is. Advantages: no unique string. Disadvantages: requires javascript to be enabled; you might require the string anyway to implement stateful web conversations.
I'd skip the whole random token thing and just store (a hash of) the comment in the session. If it matches the existing value stored in the session, then drop the comment. If not, let it through. Obviously there are problems:
It stops the user posting the same comment in different places. If this is a problem, store a hash of the comment and the id of the thing it's commenting on.
The user can press "back" and submit a different comment. I consider this a feature (it's better than dropping the comment because it matches the random token of a previous comment). Automatically interpreting this as a comment-edit is not easy.
It doesn't work if a user presses "submit" in alternate tabs. (I consider this unlikely, and it doesn't require the storage of multiple random tokens.)
You might want a random token to prevent XSRF anyway, but that's another issue (and in that case, you want to make sure that the random token is the same as "what it should be"; I'd store a long-lived one in the session).
Also, consider using prepared statements.
you can do also in jquery it's very simple.
$(document).on('click', '.className', function(){
$(this).css( 'pointer-events', 'none' );
});