2012-02-23 43 views
0

這就是我想要做的:表單提交的唯一標記似乎不起作用

防止用戶使用唯一標記提交表單兩次。我想我在這裏有正確的代碼,但它仍然沒有工作。第一次提交表格時,輸出爲「不要發送兩次」。我究竟做錯了什麼?

<?php session_start(); ?> 
<html> 
<body> 

<?php 

$_SESSION['token'] = md5(session_id() . time()); 
?> 

<?php 
if (isset($_SESSION['token'])) 
{ 
if (isset($_POST['token'])) 
{ 
    if ($_POST['token'] != $_SESSION['token']) 
    { 
     echo "Don't send twice!"; 
    } 
} 
} 
else { 

echo "Thank you for submitting"; 

} 

?> 

<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> 
<input type="hidden" name="token" value="<?php echo $_SESSION['token'] ?>" /> 
<input type="text" name="bar" /> 
<input type="submit" value="Save" /> 
</form> 

+2

您創建一個新的$ _SESSION [「令牌」]在每一頁上的負載,所以條件總是滿足(「()的時間」不斷變化的值)。 – rlanvin 2012-02-23 12:04:27

+0

重定向到同一頁面的表單提交後,防止形式重新提交 – 2012-02-23 12:10:38

+0

@雷米我改變了令牌...... $ _SESSION [「令牌」] = MD5(uniqid()); ...但我還是有同樣的問題,它說我第一次提交「不發送兩次」。你能展示一些代碼示例嗎? – user1009453 2012-02-23 12:25:24

回答

1

Thank you for submitting永遠不會被顯示出來,因爲if(isset($_SESSION['token']))條件總是滿足,因爲你生成的令牌,並直接設置會話變量上面這個if語句......這也是爲什麼你會在第一次提交後總是看到「不要發送兩次」。 當加載表單生成令牌時,將其保存在會話中,並將其放入表單中。 提交表單後,您再次從頂部開始腳本: 您的令牌現在位於帖子變量中。但是你重新創建你的會話令牌。然後你比較帖子和會話。當然他們不匹配,因爲你剛剛生成了一個新的令牌,所以當然他們不是平等的。

我建議這個結構代碼:

<html> 
<body> 
<?php 
session_start(); 

//HAS THE FORM BEEN SUBMITTED? 
if(isset($_POST)) 
{ 
    //THE FORM HAS BEEN SUBMITTED 

    //VALIDATE THE TOKEN 
    if($_POST['token'] == $_SESSION['token']) 
    { 
     //THE TOKEN WAS VALID, CONTINUE WITH PROCEDURES 

    } 
    else 
    { 
     echo 'Invalid token, please try again!'; 
    } 

} 
else 
{ 
    //FORM NOT SUBMITTED YET 

    $token = $_SESSION['token'] = md5(session_id() . time(). rand()); 
    //i recommend adding rand() otherwise there is always a 1 second window in which the token could be doubled up... 

    echo '<form action="'. $_SERVER['PHP_SELF'] .'" method="post">'; 
    echo '<input type="hidden" name="token" value="'. $token .'" />'; 
    echo '<input type="text" name="bar" />'; 
    echo '<input type="submit" value="Save" />'; 
    echo '</form>'; 
} 
?> 
</body> 
</html> 
1

的概念在這裏是有缺陷的。

  1. 瀏覽器不讓用戶使用POST兩次提交表單。他們會向用戶發出警報,告訴用戶兩次提交表單的危險性。

  2. 如果用戶加載的形式兩次,這個腳本不能避免出現兩個提交,因爲令牌是在兩個不同的形式。

我建議將提交保存在數據庫中。這可以確保同一個會話(或同一個用戶)只能保存一條記錄。

+1

非常有效的一點!如果確實只是爲了確保它沒有提交兩次,令牌不會有太大的幫助。 仍然建議使用表單標記來保護自己免受CSRF攻擊。 – olli 2013-08-14 23:29:41