The PHP code _php tutorial to really solve the form duplicate submission problem

Source: Internet
Author: User
Have seen a lot of various prevention forms repeatedly submitted JS or jquery program, but this is just a simple method, if we do not submit a form from this page, directly find the page to accept the data this JS processing method is invalid, below I use PHP some methods to solve.

Previously used JS form to prevent duplicate submission method

The code is as follows Copy Code

The following three ways to call each

The focus is actually form and input elements, p element is only paperen privately added to, the follow-up instructions have no impact, in fact, is very simple, so-called input is entered, you can fully understand the input element as a user input, Only some attributes (type) cannot be input (this is the submit), and the form element you can fully interpret it as a bag that will be used by all user input data to be submitted back to the server processing, but for the form element is worth noting is the method attribute, Generally there are get and post two methods, in fact, do not think too complicated (because in-depth do not need to understand, for the subsequent content does not have much to do with, if interested may wish to use the browser debugging tools to view the request header information and send information, such as Firebug), show that, Using get to submit a form, the value of all input elements will appear at the address bar, and post will not, for example, the browser address bar after using get to submit this form

The code is as follows Copy Code

Http://localhost/mytest/token/form.php?data=test&submit=%E6%8F%90%E4%BA%A4

Post is not visible in the address bar, you can see the following information using Fiebug

You can simply assume that get is an explicit transfer of data, while post is an implicit transfer of data, but there is a big difference that post supports more and larger data transfers.

Next, when the form code is written, let's write the server script (this is PHP). Very simple ~

The code is as follows Copy Code
if (Isset ($_post[' submit ')) {
Form submission Processing
$data = isset ($_post[' data ')? Htmlspecialchars ($_post[' data '):

'';
Insert or update database
$sql = "INSERT INTO Test (' string ') VALUES (' $data ')";
Do query
Echo $sql;
}
?>

Because this is the post to transmit the data, so use PHP $_post global variable can get to the form submitted data, all use the POST method of form data submitted to the server will be stored in the $_post global variable, you might want to try Print_r ($_post) You will understand this variable.

First check if there is a submit in the $_post array, if there is proof that the form is submitted, as if there is a call in ASP. IsPostBack, just like this is not so rigorous, but it does not matter after the problem will be solved.

After receiving the input box data, is $_post[' data ', do not forget to use Htmlspecialchars to do HTML filtering, because the HTML tag or JavaScript to prevent the problem (seemingly called XSS vulnerability). The end is splicing into the SQL statement into the database run (just here Paperen and not very detailed using some of the functions of the database operations such as mysql_query, interested in doing it yourself). Congratulations, here you have successfully completed a data entry function, but there is a place you have to improve it, after inserting the data must give the operator a hint ~ ~ ~ at least to indicate that I failed the operation or success. So the entire code paperen written as follows.

The code is as follows Copy Code
< p>!--? php
if (isset ($_post[' submit ')) {
//form submission processing
$data = isset (

$_post[' data ')? HTML Specialchars ($_post[' data '): ';
//connect
mysql_connect (' localhost ', ' root ', ' root ');

//select db
mysql_select_db (' test ');
//setting character set prevents garbled
mysql_query (' Set names ' UTF8 ');
//sql
$sql = "Insert

into ' token ' (string) VALUES (' $data ')";
//query
mysql_query ($sql);
$insert _id = mysql_in SERT_ID ();
if (

$insert _id) {
$state = 1;
} else {
$state = 0;
}
}
?

!--? php if (isset ($state)

&& $state) {//Data insertion successful?

Insert successfully returned

!--? php} else {//failed or not inserted

!--? php}?-->

HTML declaration and head and body are omitted, compared to the beginning of the code is basically to achieve the actual insertion of the database action and give the operation feedback (through the $state variable), you can copy the code and then try (of course, according to their actual situation to modify the database operation part of the code). The code is OK, the logic is OK, but there is a problem, that is, after the display of the successful insertion and then refresh the page will be executed the form processing action, and plug the data again! This is called the repetitive insertion problem. Before releasing the solution, you can think about how to solve it yourself.

Do you think that it is this page that receives the data and the display processing results that will cause this problem? Also, you can say that with some debugging tools you will find that the browser also retains the post data, so the post data will be re-submitted once the form has been submitted and then refreshed.

If there is a way to erase this temporary saved post data of the browser does not solve the problem, but the service side is not able to do this, because this is the browser itself, or we will redirect or re-refresh or repeat the submission of data.

So far perhaps you have learned the meaning and the problem of repeated submissions, if you do not choose to redirect the method then you have to think of another way, so the token solution is to come.

Just as the token itself represents permissions, operation rights, identity flags, and so on, so can I add such an identity flag to my form that when the client requests the form at the same time, it generates a token hook at the same time, makes a judgment at the time of submission, and receives and processes the form correctly. The realization of the essence is so, and reflected in the concrete implementation, it is necessary to use a kind of called the session of things. For an analysis of the session, see Wiki

The simple understanding is that the session is also a token concept, so you might be surprised, "what have I used a token for?!" "Yes, but what we're going to do is not just session but add some data on top of it to implement the form tokens we want." So let's do it!

Session in PHP is also stored in the $_session this super global variable, enable use Session_Start (), about the other server-side scripting principle, just might call the method name inconsistent. The code after adding tokens is as follows:

The code is as follows Copy Code
!--? php
//Open session
Session_Start ();
if (Isset ($_post[' submit ') && Valid_token ()) {
/ /form

Commit processing
}

/**
* Generate token
* @return string MD5 timestamp after encryption
*/
Function Create_token () {
/ /current timestamp

$timestamp = time ();
$_session[' token '] = $timestamp;
return MD5 ($TIMESTAMP);
}
/**
* Valid token
* @return bool


*/
Function Valid_token () {
if (isset ($_session[' token ') ) && isset ($_post[' token ') && $_post[' token '] = = MD5 (

$_session[' token '))
{
//if the The second token destroys
$_session[' token '] = ';
return true;
}
return false;
}
?
!--? php if (isset ($state) && $state) {//Data insertion succeeded?-->

Insert successfully returned


!-- PHP} else {//failed or no Insert action?-->

!--? php}?-->

Part of the code Paperen omitted here, because it is not the focus, actually add things only 3:

First, add an INPUT element before the end of the form, remembering that type is hidden (hidden field)

Second, add two functions, Create_token and Valid_token, which are used to generate tokens that are used to validate tokens

Thirdly, add a condition in the IF, Valid_token

That's it, it's simple, and everything is gathered in the new two functions. Paperen the token used here is simply a timestamp, and the timestamp of the request form is stored in the $_session[' token ', then the authentication token is understood to check whether the $_post[' token ' submitted by the client is MD5 $_ session[' token ') is the same, and of course there are two variables that have $_post[' token ' and $_session[' token '].

You can encapsulate this simple token pattern more nicely and extend the functionality, such as adding a form submission Timeout validation is also a good hands-on opportunity.

Finally, I enclose the Form_validation class file of the previous Paperen extension codeingeter, mainly extending the token and the form timeout. The welcome.php in the package is the controller file, put in the Applicationcontroller (if you do not want to increase the controller can open and then copy the token method to the other controller); my_form_ validation.php please put it in the applicationlibraries.

Codeingeter's Form_validation class file code

The code is as follows Copy Code

Class Welcome extends Ci_controller {


Public Function Index ()
{
$this->load->view (' welcome_message ');
}

Public Function token ()
{
$this->load->helper (Array (' form '));
$this->load->library (' form_validation ');
if ($this->input->post (' Submit ') && $this->form_validation->valid_token ())
{
Nothing
Valid_token already contains token timeout and token correct judgment, to enable token timeout, set Token_validtime to not 0
echo ' OK ';
}

Generate form Tokens
$token = $this->form_validation->create_token ();

form Example
Echo Form_Open ();
echo form_input (' token ', ');
Echo $token;
echo form_submit (' Submit ', ' submit ');
Echo Form_close ();
}
}

Form_validation_token

The code is as follows Copy Code

/**
* @abstract the Form_validation class that inherits CI increases the token on its basis
*/
Class My_form_validation extends Ci_form_validation {

/**
* Token key value
* @var String
*/
var $key = ' token ';

/**
* Form token effective time (seconds)
* @abstract If some forms need to limit the input time, set this value to 0 without limiting
* @var int seconds
*/
var $token _validtime = 5;

/**
* Debug Mode
* @var BOOL
*/
var $debug = false;

/**
* CI Object
* @var
*/
Private $_ci;

Public Function __construct ()
{
Parent::__construct ();
$this->_ci =& get_instance ();
If the configuration is not filled in Encryption_key
$encryption _key = Config_item (' Encryption_key ');
if (Empty ($encryption _key)) $this->_ci->config->set_item (' Encryption_key ', $this->key);
If the session is not loaded
if (!isset ($this->_ci->session)) $this->_ci->load->library (' Session ');
}

/**
* Set the token validity time
* @param int $second number of seconds
*/
Public Function Set_token_validtime ($second)
{
$this->token_validtime = intval ($second);
}

/**
* Get form token validity time
* @return int seconds
*/
Public Function Get_token_validtime ()
{
return $this->token_validtime;
}

/**
* Verify that the form token is legal
* @return BOOL
*/
Public Function Valid_token ()
{
if ($this->debug) return true;
Get the hash in session
$source _hash = $this->_ci->session->userdata ($this->key);
if (Empty ($source _hash)) return false;

Determine whether to timeout
if ($this->is_token_exprie ()) return false;

Committed Hash
$post _formhash = $this->_ci->input->post ($this->key);
if (Empty ($post _formhash)) return false;

if (MD5 ($source _hash) = = $post _formhash)
{
$this->_ci->session->unset_userdata ($this->key);
return true;
}
return false;
}

/**
* Generate form tokens (along with input elements)
* @return String
*/
Public Function Create_token ($output = False)
{
$code = Time (). '|' . $this->get_random (5);
$this->_ci->session->set_userdata ($this->key, $code);
$result = function_exists (' Form_hidden ')? Form_hidden ($this->key, MD5 ($code)): '';
if ($output)
{
echo $result;
}
Else
{
return $result;
}
}

/**
* Get random numbers (you can expand yourself)
* @param int $number Upper Limit
* @return String
*/
Public Function Get_random ($number)
{
Return rand (0, $number);
}

/**
* Determine if the form token is out of date
* @return BOOL
*/
Public Function Is_token_exprie ()
{
if (Empty ($this->token_validtime)) return false;
$token = $this->_ci->session->userdata ($this->key);
if (empty ($token)) return false;
$create _time = array_shift (Explode (' | ', $token));
Return (Time ()-$create _time > $this->token_validtime);
}
}

http://www.bkjia.com/PHPjc/632826.html www.bkjia.com true http://www.bkjia.com/PHPjc/632826.html techarticle have seen a lot of various prevention forms repeatedly submitted JS or jquery program, but this is only a simple method, if we do not submit a form from this page, directly find the data to accept the page ...

  • Related Article

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.