php表單加入Token防止重復(fù)提交的方法分析
本文實(shí)例講述了php表單加入Token防止重復(fù)提交的方法。分享給大家供大家參考,具體如下:
Token淺談
Token,就是令牌,最大的特點(diǎn)就是隨機(jī)性,不可預(yù)測(cè)。一般黑客或軟件無(wú)法猜測(cè)出來(lái)。
那么,Token有什么作用?又是什么原理呢?
Token一般用在兩個(gè)地方——防止表單重復(fù)提交、anti csrf攻擊(跨站點(diǎn)請(qǐng)求偽造)。
兩者在原理上都是通過(guò)session token來(lái)實(shí)現(xiàn)的。當(dāng)客戶端請(qǐng)求頁(yè)面時(shí),服務(wù)器會(huì)生成一個(gè)隨機(jī)數(shù)Token,并且將Token放置到session當(dāng)中,然后將Token發(fā)給客戶端(一般通過(guò)構(gòu)造hidden表單)。下次客戶端提交請(qǐng)求時(shí),Token會(huì)隨著表單一起提交到服務(wù)器端。
然后,如果應(yīng)用于“anti csrf攻擊”,則服務(wù)器端會(huì)對(duì)Token值進(jìn)行驗(yàn)證,判斷是否和session中的Token值相等,若相等,則可以證明請(qǐng)求有效,不是偽造的。
不過(guò),如果應(yīng)用于“防止表單重復(fù)提交”,服務(wù)器端第一次驗(yàn)證相同過(guò)后,會(huì)將澀session中的Token值更新下,若用戶重復(fù)提交,第二次的驗(yàn)證判斷將失敗,因?yàn)橛脩籼峤坏谋韱沃械腡oken沒(méi)變,但服務(wù)器端session中Token已經(jīng)改變了。
上面的session應(yīng)用相對(duì)安全,但也叫繁瑣,同時(shí)當(dāng)多頁(yè)面多請(qǐng)求時(shí),必須采用多Token同時(shí)生成的方法,這樣占用更多資源,執(zhí)行效率會(huì)降低。因此,也可用cookie存儲(chǔ)驗(yàn)證信息的方法來(lái)代替session Token。比如,應(yīng)對(duì)“重復(fù)提交”時(shí),當(dāng)?shù)谝淮翁峤缓蟊惆岩呀?jīng)提交的信息寫到cookie中,當(dāng)?shù)诙翁峤粫r(shí),由于cookie已經(jīng)有提交記錄,因此第二次提交會(huì)失敗。
不過(guò),cookie存儲(chǔ)有個(gè)致命弱點(diǎn),如果cookie被劫持(xss攻擊很容易得到用戶cookie),那么又一次gameover。黑客將直接實(shí)現(xiàn)csrf攻擊。

所以,安全和高效相對(duì)的。具體問(wèn)題具體對(duì)待吧。
php表單加入Token防止重復(fù)提交
原理在于生成一個(gè)隨機(jī)字符串放在session里,提交表單后來(lái)驗(yàn)證這個(gè)字符串,可以做到防止他人自己寫form來(lái)欺騙提交,重復(fù)提交或者雙擊提交。

簡(jiǎn)單的用php實(shí)現(xiàn)的代碼如下:
<?php
/*
* PHP簡(jiǎn)單利用token防止表單重復(fù)提交
* 此處理方法純粹是為了給初學(xué)者參考
*/
session_start();
function set_token() {
$_SESSION['token'] = md5(microtime(true));
}
function valid_token() {
$return = $_REQUEST['token'] === $_SESSION['token'] ? true : false;
set_token();
return $return;
}
//如果token為空則生成一個(gè)token
if(!isset($_SESSION['token']) || $_SESSION['token']=='') {
set_token();
}
if(isset($_POST['test'])){
if(!valid_token()){
echo "token error";
}else{
echo '成功提交,Value:'.$_POST['test'];
}
}
?>
<form method="post" action="">
<input type="hidden" name="token" value="<?php echo $_SESSION['token']?>">
<input type="text" name="test" value="Default">
<input type="submit" value="提交" />
</form>
上面的比較簡(jiǎn)單一點(diǎn)的方法,下面的代碼更加安全一點(diǎn)。
Token.php
<?php
/*
* Created on 2013-3-25
*
* To change the template for this generated file go to
* Window - Preferences - PHPeclipse - PHP - Code Templates
*/
function getToken($len = 32, $md5 = true) {
# Seed random number generator
# Only needed for PHP versions prior to 4.2
mt_srand((double) microtime() * 1000000);
# Array of characters, adjust as desired
$chars = array (
'Q',
'@',
'8',
'y',
'%',
'^',
'5',
'Z',
'(',
'G',
'_',
'O',
'`',
'S',
'-',
'N',
'<',
'D',
'{',
'}',
'[',
']',
'h',
';',
'W',
'.',
'/',
'|',
':',
'1',
'E',
'L',
'4',
'&',
'6',
'7',
'#',
'9',
'a',
'A',
'b',
'B',
'~',
'C',
'd',
'>',
'e',
'2',
'f',
'P',
'g',
')',
'?',
'H',
'i',
'X',
'U',
'J',
'k',
'r',
'l',
'3',
't',
'M',
'n',
'=',
'o',
'+',
'p',
'F',
'q',
'!',
'K',
'R',
's',
'c',
'm',
'T',
'v',
'j',
'u',
'V',
'w',
',',
'x',
'I',
'$',
'Y',
'z',
'*'
);
# Array indice friendly number of chars;
$numChars = count($chars) - 1;
$token = '';
# Create random token at the specified length
for ($i = 0; $i < $len; $i++)
$token .= $chars[mt_rand(0, $numChars)];
# Should token be run through md5?
if ($md5) {
# Number of 32 char chunks
$chunks = ceil(strlen($token) / 32);
$md5token = '';
# Run each chunk through md5
for ($i = 1; $i <= $chunks; $i++)
$md5token .= md5(substr($token, $i * 32 - 32, 32));
# Trim the token
$token = substr($md5token, 0, $len);
}
return $token;
}
?>
form.php
<?php
include_once("token.php");
$token = getToken();
session_start();
$_SESSION['token'] = $token;
?>
<form action="action.php" method="post"
<input type="hidden" name="token" value="<?=$token?>" />
<!-- 其他input submit之類的 -->
</form>
action.php
<?php
session_start();
if($_POST['token'] == $_SESSION['token']){
unset($_SESSION['token']);
echo "這是一個(gè)正常的提交請(qǐng)求";
}else{
echo "這是一個(gè)非法的提交請(qǐng)求";
}
?>
更多關(guān)于PHP相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《php程序設(shè)計(jì)安全教程》、《php安全過(guò)濾技巧總結(jié)》、《PHP運(yùn)算與運(yùn)算符用法總結(jié)》、《PHP網(wǎng)絡(luò)編程技巧總結(jié)》、《PHP基本語(yǔ)法入門教程》、《php操作office文檔技巧總結(jié)(包括word,excel,access,ppt)》、《php面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》、《php字符串(string)用法總結(jié)》、《php+mysql數(shù)據(jù)庫(kù)操作入門教程》及《php常見(jiàn)數(shù)據(jù)庫(kù)操作技巧匯總》
希望本文所述對(duì)大家PHP程序設(shè)計(jì)有所幫助。
相關(guān)文章
詳談symfony window下的安裝 安裝時(shí)候出現(xiàn)的問(wèn)題以及解決方法
下面小編就為大家?guī)?lái)一篇詳談symfony window下的安裝 安裝時(shí)候出現(xiàn)的問(wèn)題以及解決方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09
PHP設(shè)計(jì)模式之模板方法模式定義與用法詳解
這篇文章主要介紹了PHP設(shè)計(jì)模式之模板方法模式,結(jié)合實(shí)例形式詳細(xì)分析了php設(shè)計(jì)模式中模板方法模式的概念、原理、定義、用法及相關(guān)注意事項(xiàng),需要的朋友可以參考下2018-04-04
PHP實(shí)現(xiàn)提取多維數(shù)組指定一列的方法總結(jié)
這篇文章主要介紹了PHP實(shí)現(xiàn)提取多維數(shù)組指定一列的方法,結(jié)合實(shí)例形式總結(jié)分析了PHP針對(duì)多維數(shù)組的遍歷、轉(zhuǎn)換、提取等相關(guān)操作技巧,需要的朋友可以參考下2019-12-12
Mysql中l(wèi)imit的用法方法詳解與注意事項(xiàng)
mysql的數(shù)據(jù)一般都是用limit控制數(shù)量,它的使用方法也是需要注意的。2008-04-04
ajax 的post方法實(shí)例(帶循環(huán))
在最近的項(xiàng)目中,為了能解決在大數(shù)據(jù)查詢中出現(xiàn)的超時(shí)問(wèn)題,需要將大數(shù)據(jù)拆分成小數(shù)據(jù),然后進(jìn)行循環(huán)處理。本人經(jīng)驗(yàn)不足,技術(shù)有限,只能想到用ajax來(lái)傳送數(shù)據(jù)。2011-07-07
PHP實(shí)現(xiàn)簡(jiǎn)單漢字驗(yàn)證碼
大家知道簡(jiǎn)單數(shù)字或者字母驗(yàn)證碼很容易被破解,但是算式驗(yàn)證碼或者中文漢字驗(yàn)證碼不容易被破解,所以建議大家在使用驗(yàn)證碼的時(shí)候,盡量用算式驗(yàn)證碼或者中文漢字驗(yàn)證碼。2015-07-07

