PHP: Avoid duplicate submissions and check data routing

Source: Internet
Author: User
Tags commit copy header md5 php file rand strlen
Avoid duplicate submission of data. Check the routing, whether it is an external commit match to perform the action (if there are multiple logic on the same page, such as add, delete, modify put into a PHP file operation) The token here is a hidden form item that is written to form when the page is displayed (type= Hidden).

PHP Token (token) design

Design objectives:

Token can not be clear, if it is clear, it is too dangerous, so to use a certain encryption. The cipher must be reversible. My algorithm is very stupid, so the use of a ready-made online method.

How to achieve the goal:

How do I avoid duplicate submissions?

In the session, you save an array, which is stored in a successfully submitted token. In the background processing, first determine whether the token is in this array, if it exists, the description is repeated submissions.

How to check the antecedents?

Optional, this token is added to the current session_id when it is generated. If someone else copy your HTML (token a copy), in the submission, theoretically token contains session_id not equal to the current session_id, You can judge this submission as an external submission.

How do I match an action to be performed?

In the token, to the token of the action name into this token, so, in processing, the action to solve the comparison on the line.

The Gtoken I wrote earlier could not reach the second one mentioned above, and I modified it today to add the function 2. Personal feeling is OK.

Please see the code, feel where there is unreasonable place, please enlighten me! Thank you.

Encryption I was looking for a method of the Internet, slightly modified.

GEncrypt.inc.php:

Class Gencrypt extends Gsuperclass {

protected static function keyed ($txt, $encrypt _key) {

$encrypt _key = MD5 ($encrypt _key);

$ctr = 0;

$tmp = "";

for ($i =0; $i

if ($ctr ==strlen ($encrypt _key)) $ctr = 0;

$tmp. = substr ($txt, $i, 1) ^ substr ($encrypt _key, $ctr, 1);

$ctr + +;

}

return $tmp;

}

public static function Encrypt ($txt, $key) {

$encrypt _key = MD5 (rand (0,32000));

$encrypt _key = MD5 ((float) Date ("Ymdhis") + rand (10000000000000000,99999999999999999). Rand (100000,999999));

$ctr = 0;

$tmp = "";

for ($i =0; $i

if ($ctr ==strlen ($encrypt _key)) $ctr = 0;

$tmp. = substr ($encrypt _key, $ctr, 1). (Substr ($txt, $i, 1) ^ substr ($encrypt _key, $ctr, 1));

$ctr + +;

}

Return Base64_encode (self::keyed ($tmp, $key));

}

public static function Decrypt ($txt, $key) {

$txt = self::keyed (Base64_decode ($txt), $key);

$tmp = "";

for ($i =0; $i

$MD 5 = substr ($txt, $i, 1);

$i + +;

$tmp. = (substr ($txt, $i, 1) ^ $md 5);

}

return $tmp;

}

}

?>

GToken.inc.php

Method:

A,grantetoken parameter: FormName, which is the action name, key is the encryption/decryption key.

Returns a string, in the form of: encryption (FORMNAME:SESSION_ID)

B,istoken parameters: Token that is the result of Grantetoken, FormName, action name, fromcheck whether to check the antecedents, if true, but also to determine token whether the session_id and the current session_id one to.

C,droptoken, when a successful action is executed, call this function, and write this token into the session,

/**

* Principle: When requesting allocation of token, try to allocate a unique token, base64 (time + rand + action)

* If submitted, place this token record stating that this token is used and can be followed to avoid duplicate submissions.

*

*/

Class Gtoken {

/**

* Get all the current token

*

* @return Array

*/

public static function Gettokens () {

$tokens = $_session[gconfig::session_key_token];

if (Empty ($tokens) &&!is_array ($tokens)) {

$tokens = Array ();

}

return $tokens;

}

/**

* To produce a new token

*

* @param string $formName

* @param encryption Key $key

* @return String

*/

public static function Grantetoken ($formName, $key = Gconfig::encrypt_key) {

$token = Gencrypt::encrypt ($formName. ":". session_id (), $key);

return $token;

}

/**

* Delete token, in fact, add an element to an array of sessions to show that the token has been used to avoid duplication of data submissions.

*

* @param string $token

*/

public static function Droptoken ($token) {

$tokens = Self::gettokens ();

$tokens [] = $token;

Gsession::set (Gconfig::session_key_token, $tokens);

}

/**

* Check to see if the specified token

*

* @param string $token The token value to check

* @param string $formName

* @param boolean $fromCheck whether to check the routing and, if true, to determine whether the attached session_id in token is the same as the current session_id.

* @param string $key encryption key

* @return Boolean

*/

public static function Istoken ($token, $formName, $fromCheck = False, $key = Gconfig::encrypt_key) {

$tokens = Self::gettokens ();

if (In_array ($token, $tokens))//If present, the description is in use token

return false;

$source = Split (":", Gencrypt::d ecrypt ($token, $key));

if ($fromCheck)

return $source [1] = = session_id () && $source [0] = = $formName;

Else

return $source [0] = = $formName;

}

}

?>

Example:

First from the $_post to take out token, with Istoken judge.

Include (".. /common.inc.php ");

$token = $_post["token"];

if (Gtoken::istoken ($token, "Adminlogin", true)) {

$vCode = $_post["Vcode"];

if (Strtoupper ($vCode)!= strtoupper ($_session[gconfig::session_key_validate_code)) {

throw new Exception ("Incorrect verification Code!");

}

$vo = new Vo_admin ();

$vo->setnickname ($_post["name"]);

$vo->setpwd ($_post["pwd"]);

$mo = new Mo_admin ();

$mo->setvo ($VO);

$f = $mo->login ();

if (! $f) {

throw new Exception ("Username or password incorrect!");

}else{

Gtoken::d Roptoken ($token);

Header ("Location:"). Gdir::getrelativepath ("/admin/index.php"));

echo "Here"; If it is externally submitted, this sentence will not print out!

}

}

$sFile = Gdir::getabspath (gconfig::D ir_serialize, "Admin/login");

$TPL = Gserialize::load ($sFile);

if ($tpl = = False) {

$TPL = new Gtpl (gconfig::D Ir_skin, Gconfig::D ebug_tpl_file);

$TPL->load Array (

"Header" => "admin/header.html",

"Footer" => "admin/footer.html",

"Admlogin" => "admin/login.html",

"Admloginjs" => "admin/loginjs.html"

));

Gserialize::save ($TPL, $sFile);

}

$tpl->assign ("title", "Admin login");

$TPL->assign ("Path", Gdir::getrelativepath (Site_dir));

$tpl->assign ("Vimg", Gdir::getrelativepath ("/vimg.php"));

if (mo_admin::islogined ()) {

$tpl->parseblock ("blk_logined");

}else {

$TPL->assign ("token", Gtoken::grantetoken ("Adminlogin"));

$tpl->parseblock ("blk_loadscripts", "Cond_notlogin");

$tpl->parseblock ("Blk_notlogin");

}

echo $tpl->parse ("header");

echo $tpl->parse ("Admlogin");

echo $tpl->parse ("footer");

echo $tpl->parse ("Admloginjs"); Webjx.com

?>

It all looked as if there was no problem.

If you want to determine whether the matching action is performed, you can change the formname in the Istoken, run, very well, no match. Prove this success.

Whether I can avoid repeated submissions, I have no validation, too simple logic.

The rest is to determine whether the routing check is working properly.

The above example generates HTML copy to a local Web page (to achieve the purpose of a different domain), runs, checks out, and does not perform an action (you need to set the third argument of Istoken to true).

Set the third parameter of Istoken to False, commit, and execute the specified action!

OK, so far, do not know where there is a bug, this will be in the long-term use of slowly debugging changes!



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.