2013-08-20 23 views
0

所以基本上,我試圖做一個簡單但安全的,被遺忘的密碼腳本。如何解決這個PHP忘記密碼腳本?

有兩個腳本,一個允許用戶輸入他們的電子郵件地址。然後,他們會向他們發送帶有鏈接的電子郵件,他們必須訪問以保存新密碼。

第二個腳本是鏈接導向的地方。該腳本保存新密碼。

爲了安全起見,我在我的數據庫中創建了一個名爲'token'的新表。它有三個領域;令牌,電子郵件,使用。令牌是一個由10個字母和數字組成的隨機生成的字符串,電子郵件就是用戶的電子郵件地址,並且使用的是1或0的整數,表示令牌是否已被使用。

一旦閱讀了這兩個腳本,您將能夠更加了解我的結構。它們不會很長,也不會很複雜。

到底哪裏出問題了

好了,只有一個很小的事情去錯了,這是復位password.php腳本中。這是用戶在收到電子郵件後來到的地方。基本上,我輸入一個新的密碼,然後點擊「重置密碼」,但沒有任何反應。沒有顯示錯誤或確認,以及我的數據庫中沒有任何更改。我似乎無法調試此功能,並且一直在尋找並嘗試幾個小時。所有的幫助和建議將不勝感激。

請記住,我仍然是PHP和MySQL的新手。用PHP已經工作了大約8周了,而MySQL只有2

忘記-password.php

<?php 
//Forgotten password script 

    //Variable to save errors 
    $errors = array(); 

    $email = $_POST['email']; 

    include 'config.php'; 
    mysql_connect("$db_host", "$db_username", "$db_password")or die("cannot connect"); 
    mysql_select_db("$db_name")or die("cannot select DB"); 

    $query = "SELECT email FROM users WHERE email='" . $email . "'"; 
    $result = mysql_query($query); 
    $num = mysql_num_rows($result); 
    if($num==0) 
    { 
     echo ("<div style='color:red;'>Email address is not registered</div>"); 
     die(); 
    } 

    $token = getRandomString(10); 
    $query = "INSERT INTO tokens (token,email) VALUES ('".$token."','".$email."')"; 
    mysql_query($query); 

    //function to renerate the token 
    function getRandomString($length) 
    { 
     $validCharacters = "ABCDEFGHIJKLMNPQRSTUXYVWZ123456789"; 
     $validCharNumber = strlen($validCharacters); 
     $result = ""; 

     for ($i = 0; $i < $length; $i++) 
     { 
      $index = mt_rand(0, $validCharNumber - 1); 
      $result .= $validCharacters[$index]; 
     } 
     return $result; 
    } 

    //Send the reset link to the user 
    function mailresetlink($to,$token) 
    { 
     $subject = "Password Reset"; 
     $message = ' 
     <html> 
     <head> 
     <title>Password Reset</title> 
     </head> 
     <body> 
     <p>Click on the given link to reset your password <a href="http://domain.com/reset-password.php?token='.$token.'">Reset Password</a></p> 

     </body> 
     </html> 
     '; 
     $headers = "MIME-Version: 1.0" . "\r\n"; 
     $headers .= "Content-type:text/html;charset=iso-8859-1" . "\r\n"; 
     $headers .= 'From: Password Reset <[email protected]>' . "\r\n"; 

     if(mail($to,$subject,$message,$headers)) 
     { 
      echo "We have sent the password reset link to your email at <strong>".$to."</strong>"; 
     } 
    } 

    //If email is posted, send the email 
    if(isset($_POST['email'])) 
    { 
     mailresetlink($email,$token); 
    } 


?> 




<table align="center" style="padding-bottom:40px;"> 
    <form action="<?php $_SERVER['PHP_SELF']; ?>" method="post"> 
    <tr> 
    <td>Email Address: </td> 
    <td><input type="text" name="email" /></td> 
    </tr> 
    <tr> 
    <td colspan="2" align="center"><input type="submit" value="Reset My Password" /></td></tr> 
    <input type="hidden" name="register" value="TRUE" /> 
</form> 
</table> 

復位password.php

<?php 
//Reset password script 

    $token = $_GET['token']; 
    $email; 

    include 'config.php'; 
    mysql_connect("$db_host", "$db_username", "$db_password") or die("cannot connect"); 
    mysql_select_db("$db_name")or die("cannot select DB"); 

    if(!isset($_POST['newpassword'])) 
    { 
     $query = "SELECT email FROM tokens WHERE token='" . $token . "' AND used = 0"; 
     $result = mysql_query($query); 
     while($row = mysql_fetch_array($result)) 
     { 
      $email = $row['email']; 
     } 


     if ($email != '') 
     { 
      $_SESSION['email'] = $email; 
     } 
     else 
     { 
      echo "Invalid link or Password already changed"; 
     } 
    } 


    $pass = $_POST['newpassword']; 
    $email = $_SESSION['email']; 

    //Save new password 
    if(isset($_POST['newpassword']) && isset($_SESSION['email'])) 
    { 
     $query = "UPDATE users SET password = SHA('$password') WHERE email='" . $email . "'"; 
     $result = mysql_query($query); 
     if($result) 
     { 
      mysql_query("UPDATE tokens SET used=1 WHERE token='" . $token . "'"); 
     } 
     echo "Your password has been changed successfully"; 
     if(!$result) 
     { 
      echo "An error occurred. Please try the again or contact us at [email protected]"; 
     } 
    } 

?> 



<table align="center" style="padding-bottom:40px;"> 
    <form action="<?php $_SERVER['PHP_SELF']; ?>" method="post"> 
    <tr> 
    <td>New Password:</td> 
    <td><input type="password" name="newpassword" id="password"/></td> 
    </tr> 
    <tr> 
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr> 
    <input type="hidden" name="reset" value="TRUE" /> 
</form> 
</table> 

請,如果你需要更多的信息或代碼,請不要猶豫,問。

在此先感謝!

+0

從米奇答案應該解決您的問題。如前所述,該功能並不安全,在早期的答案中,它試圖指出[安全密碼重置](http://stackoverflow.com/a/18331345/575765)過程的樣子。 – martinstoeckli

+0

@martinstoeckli - 正如您在Mitch的帖子中發佈的新評論所看到的,他的回答不幸並沒有解決我在使用我的代碼時遇到的問題。 – Fizzix

+0

在第一個獲取請求中,您從數據庫中獲取電子郵件並將其存儲在會話中,然後在第二個發佈請求中從會話中讀取電子郵件。這不是必要的,只有在必要時纔可以閱讀電子郵件(提交表單後)。在你的例子中它不起作用的原因是,你沒有在腳本的開頭調用'session_start()',但是真的,在這裏沒有必要進行會話。 – martinstoeckli

回答

5

輸入新的密碼參數後,我沒有看到任何地方將令牌參數傳遞給重置頁面上的服務器。你應該有另一個隱藏的控制,我期望。 $_SERVER['PHP_SELF']不返回查詢字符串參數。這可能是你目前問題的原因。

具體來說,

<table align="center" style="padding-bottom:40px;"> 
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> 
    <tr> 
    <td>New Password:</td> 
    <td><input type="password" name="newpassword" id="password"/></td> 
    </tr> 
    <tr> 
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr> 
    <input type="hidden" name="reset" value="TRUE" /> 
</form> 
</table> 

應該

<table align="center" style="padding-bottom:40px;"> 
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post"> 
    <tr> 
    <td>New Password:</td> 
    <td><input type="password" name="newpassword" id="password"/></td> 
    </tr> 
    <tr> 
    <td colspan="2" align="center"><input type="submit" value="Change Password"></td></tr> 
    <input type="hidden" name="reset" value="TRUE" /> 
    <input type="hidden" name="token" value="<?php echo $_REQUEST['token']; ?>" /> 
</form> 
</table> 

請確保您還更改任何$_GET['token'] s到$_REQUEST['token']因爲它會在第一時間拿到,然後發佈第二。

這就是說,你的一個更大的問題是我能夠通過指定' or 1=1 or '作爲我的標記來繞過所有的安全。或者,我可以平均,做故事的一個不錯'; update users set password = SHA('IKnowThisPassword') where username = 'admin'; --

道德被參數化的SQL(How can I prevent SQL injection in PHP?

+0

@Sonali,錯字,已更新。 – Mitch

+0

」method =「post」> echo在這裏丟失 –

+0

更新後使用回聲也@Mitch –