2017-02-21 59 views
-3

我爲我的網站(www.qbstaxsubmission.co.uk)設置了一個PHP丟失密碼頁面,並且創建發送給用戶的密碼丟失郵件的代碼工作正常。但是,當用戶點擊電子郵件鏈接,他到達一個新的密碼PHP頁面。這是此頁面上的腳本,它產生一條錯誤消息'更新恢復密鑰時發生註冊失敗:INSERT',它會啓動我的樣式錯誤頁面以將用戶轉移回標準登錄頁面。PHP MSQLI忘記密碼重置頁面

所以我的問題是我無法看到我的新password2.php有什麼問題。有人能幫忙嗎?

下面是完整的新password2.php代碼:

<?php 
ob_start(); 
include ('config.php'); 
include ('function.php'); 
$error_msg = ""; 

$token = $_GET['token']; 
$userID = UserID($email); 
$verifytoken = verifytoken($userID, $token); 

// Sanitize and validate the data passed in 
if (isset($_POST['submit'],$_POST['username'], $_POST['email'],  $_POST['p'])) { 
$email = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_STRING); 
$username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING); 
$new_password = filter_input(INPUT_POST, 'new_password', FILTER_SANITIZE_STRING); 
$retype_password = filter_input(INPUT_POST, 'retype_password', FILTER_SANITIZE_STRING); 
$id = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_STRING);} 

$new_password = filter_input(INPUT_POST, 'p', FILTER_SANITIZE_STRING); 
if (strlen($new_password) != 128) { 
// The hashed pwd should be 128 characters long. 
// If it's not, something really odd has happened 
$error_msg .= '<p class="error">Invalid password configuration.</p>'; 
} 

$prep_stmt = "SELECT id FROM members WHERE email = ? LIMIT 1"; 
$stmt = $db ->prepare($prep_stmt);  
if ($stmt) { 
$stmt->bind_param('s', $email); 
$stmt->execute(); 
$stmt->store_result(); 

if ($stmt->num_rows == 1) { 
// A user with this email address already exists 
$error_msg .= '<p class="error">A user with this email address already exists.</p>'; 
} 
} else { 
$error_msg .= '<p class="error">Database error</p>'; 
} 

if($new_password != $retype_password) { 
// Create a random salt 
$salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE)); 
// Create salted password 
$new_password = hash('sha512', $random_salt . $salt); 

} 

// Insert the new hashed password into the database 
if ($insert_stmt = $db->prepare("UPDATE members SET password = ? WHERE id = ? ")) { 
$insert_stmt->bind_param('si', $newpassword, $id); 
// Execute the prepared query. 
if (!$insert_stmt->execute()) { 
header('Location: ../error.php?err=Database Registration failure: INSERT'); 
} 

// Update recovery key  
if ($insert_stmt = $db->prepare("UPDATE recovery_keys SET valid = 0 WHERE id = ? AND token = ? ")); 
$insert_stmt->bind_param('is', $id, $token); 
// Execute the prepared query. 
if ($insert_stmt->execute()) 
$msg = 'Your password has changed successfully. Please login with your new password.'; 

}else 
{ 


header('Location: ../error.php?err=Registration failure in updating recovery key: INSERT'); } 

{exit();} 


?> 

當上面的代碼運行時我得到了一個空白頁面,在該網站的鏈接顯示的正確的令牌代碼。

這個password2.php頁面包含一個功能頁面,如下所示。

function checkUser($email) 
{ 
global $db; 

$query = mysqli_query($db, "SELECT id FROM members WHERE email = '$email'"); 

if(mysqli_num_rows($query) > 0) 
{ 
return 'true'; 
}else 
{ 
return 'false'; } 
} 

function id($email) 
{ 
global $db; 

$query = mysqli_query($db, "SELECT id FROM members WHERE email = '$email'"); 
$row = mysqli_fetch_assoc($query); 

return $row['id']; 
} 


function generateRandomString($length = 25) { 
// This function has taken from stackoverflow.com 

$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; 
$charactersLength = strlen($characters); 
$randomString = ''; 
for ($i = 0; $i < $length; $i++) { 
$randomString .= $characters[rand(0, $charactersLength - 1)]; 
} 
return md5($randomString); 
} 

function send_mail($to, $token) 
{ 
require 'PHPMailer/PHPMailerAutoload.php'; 
$mail = new PHPMailer; 
//$mail->SMTPDebug = 3;  

$mail->isSMTP(); 
$mail->Host = ''; 
$mail->SMTPAuth = true; 
$mail->Username = ''; 
$mail->Password = ''; 
$mail->SMTPSecure = 'ssl'; 
$mail->Port = 465; 
$mail->SetFrom = ''; 
$mail->FromName = ''; 
$mail->addAddress($to); 
$mail->addReplyTo('', 'Reply'); 
$mail->isHTML(true);  
$mail->Subject = 'Company Password Recovery Instruction'; 
$link = 'x.php?email='.$to.'&token='.$token; 
$mail->Body = "<b>Hi</b><br><br>You have just requested a new password for your company account with QBS Tax Submission. <a href='$link' target='_blank'>Click here</a> to reset your password. If you are unable to click the link then copy the hyper link below and paste into your browser to reset your password.<br><i>". $link."</i>"; 

$mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; 
if(!$mail->send()) { 
return 'fail'; 
} else { 
return 'success'; 
} 
} 

function verifytoken($id, $token) 
{ 
global $db; 
$query = mysqli_query($db, "SELECT valid FROM recovery_keys WHERE id = $id AND token = '$token'"); 
$row = mysqli_fetch_assoc($query); 
if(mysqli_num_rows($query) > 0) 
{ 
if($row['valid'] == 1) 
{ 
return 1; 
}else 
{ 
return 0; 
} 
}else 
{ 
return 0; 
} 

} 

function login($email, $password, $mysqli) { 
// Using prepared statements means that SQL injection is not possible. 
if ($stmt = $mysqli->prepare("SELECT id, username, email, password, salt 
       FROM members 
           WHERE email = ? LIMIT 1")) { 
$stmt->bind_param('s', $email); // Bind "$email" to parameter. 
$stmt->execute(); // Execute the prepared query. 
$stmt->store_result(); 
// get variables from result. 
$stmt->bind_result($id, $username, $db_password, $salt); 
$stmt->fetch(); 
// hash the password with the unique salt. 
$password = hash('sha512', $password . $salt); 
if ($stmt->num_rows == 1) { 
// If the user exists we check if the account is locked 
// from too many login attempts 
if (checkbrute($id, $mysqli) == true) { 
// Account is locked 
// Send an email to user saying their account is locked 
return false; 
} else { 
// Check if the password in the database matches 
// the password the user submitted. 
if ($db_password == $password) { 
// Password is correct! 
// Get the user-agent string of the user. 
$user_browser = $_SERVER['HTTP_USER_AGENT']; 
// XSS protection as we might print this value 
$id = preg_replace("/[^0-9]+/", "", $id); 
$_SESSION['id'] = $id; 
// XSS protection as we might print this value 
$username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); 
$_SESSION['username'] = $username; 
$_SESSION['login_string'] = hash('sha512', $password . $user_browser); 
// Login successful. 
return true; 
} else { 
// Password is not correct 
// We record this attempt in the database 
$now = time(); 
if (!$mysqli->query("INSERT INTO login_attempts(id, time) 
VALUES ('$id', '$now')")) { 
header("Location: ../error.php?err=Database error: login_attempts"); 
exit(); 
} 
return false; 
} 
} 
} else { 
// No user exists. 
return false; 
} 
} else { 
// Could not create a prepared statement 
header("Location: ../error.php?err=Database error: cannot prepare statement"); 
exit(); 
} 
} 
function checkbrute($id, $mysqli) { 
// Get timestamp of current time 
$now = time(); 
// All login attempts are counted from the past 2 hours. 
$valid_attempts = $now - (2 * 60 * 60); 
if ($stmt = $mysqli->prepare("SELECT time 
           FROM login_attempts 
           WHERE id = ? AND time > '$valid_attempts'")) { 
$stmt->bind_param('i', $id); 
// Execute the prepared query. 
$stmt->execute(); 
$stmt->store_result(); 
// If there have been more than 5 failed logins 
if ($stmt->num_rows > 5) { 
return true; 
} else { 
return false; 
} 
} else { 
// Could not create a prepared statement 
header("Location: ../error.php?err=Database error: cannot prepare statement"); 
exit(); 
} 
} 
function login_check($mysqli) { 
// Check if all session variables are set 
if (isset($_SESSION['id'], $_SESSION['username'],  $_SESSION['login_string'])) { 
$id = $_SESSION['id']; 
$login_string = $_SESSION['login_string']; 
$username = $_SESSION['username']; 
// Get the user-agent string of the user. 
$user_browser = $_SERVER['HTTP_USER_AGENT']; 
if ($stmt = $mysqli->prepare("SELECT password 
        FROM members 
        WHERE id = ? LIMIT 1")) { 
// Bind "$id" to parameter. 
$stmt->bind_param('i', $id); 
$stmt->execute(); // Execute the prepared query. 
$stmt->store_result(); 
if ($stmt->num_rows == 1) { 
// If the user exists get variables from result. 
$stmt->bind_result($password); 
$stmt->fetch(); 
$login_check = hash('sha512', $password . $user_browser); 
if ($login_check == $login_string) { 
// Logged In! 
return true; 
} else { 
// Not logged in 
return false; 
} 
} else { 
// Not logged in 
return false; 
} 
} else { 
// Could not prepare statement 
header("Location: ../error.php?err=Database error: cannot prepare statement"); 
exit(); 
} 
} else { 
// Not logged in 
return false; 
} 
} 
function esc_url($url) { 
if ('' == $url) { 
    return $url; 
} 
$url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url); 

$strip = array('%0d', '%0a', '%0D', '%0A'); 
$url = (string) $url; 

$count = 1; 
while ($count) { 
    $url = str_replace($strip, '', $url, $count); 
} 

$url = str_replace(';//', '://', $url); 
$url = htmlentities($url); 

$url = str_replace('&amp;', '&#038;', $url); 
$url = str_replace("'", '&#039;', $url); 
if ($url[0] !== '/') { 
    // We're only interested in relative links from $_SERVER['PHP_SELF'] 
    return ''; 
} else { 
    return $url; 
} 
} 
+4

'SET password = salt'$ new_password''這是一個問題。 –

+1

as'if($ insert_stmt = $ db-> prepare(「UPDATE recovery_keys SET valid = 0 WHERE userID = $ userID AND token ='$ token'」)); $ insert_stmt-> bind_param('ss',$ userID,$ token);' - 檢查錯誤,你有幾個。 http://php.net/manual/en/mysqli.error.php --- http://php.net/manual/en/function.error-reporting.php –

+2

不要推出自己的哈希。使用[password_hash](http://php.net/manual/en/function.password-hash.php)。它更容易管理 – Machavity

回答

1

我believ這是那裏的問題是:

if (! $insert_stmt->execute()) 
    $msg = 'Your password has changed successfully. Please login with your new password.'; 

}else{..} 

if (! $insert_stmt->execute())這意味着如果查詢失敗回顯密碼失敗.....

的原因,你的代碼始終顯示更新恢復密鑰時註冊失敗:INSERT它的原因是您指示您的代碼在查詢未失敗時必須生成該代碼。

而你的代碼全部搞亂了,你需要清理它。

這是應該看起來如何。

if ($insert_stmt = $db->prepare("UPDATE recovery_keys SET valid = 0 WHERE userID = ? AND token = ? ")); 
    $insert_stmt->bind_param('ss', $userID, $token); 
    // Execute the prepared query. 
    if ($insert_stmt->execute()) 
    $msg = 'Your password has changed successfully. Please login with your new password.'; 

    }else 
    { 
    $msg = "Password doesn't match"; 

    header('Location: ../error.php?err=Registration failure in updating recovery key: INSERT'); } 

    {exit();} 

編輯

試圖清理一些亂七八糟的代碼。現在該怎麼看。

<?php 
ob_start(); 
include('config.php'); 
include('function.php'); 
$error_msg = ""; 

$token  = $_GET['token']; 
$userID  = UserID($email); 
$verifytoken = verifytoken($userID, $token); 

// Sanitize and validate the data passed in 
if (isset($_POST['submit'], $_POST['username'], $_POST['email'], $_POST['p'])) { 
    $email   = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_STRING); 
    $username  = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING); 
    $new_password = filter_input(INPUT_POST, 'new_password', FILTER_SANITIZE_STRING); 
    $retype_password = filter_input(INPUT_POST, 'retype_password', FILTER_SANITIZE_STRING); 
    $id    = filter_input(INPUT_POST, 'id', FILTER_SANITIZE_STRING); 
} 

$new_password = filter_input(INPUT_POST, 'p', FILTER_SANITIZE_STRING); 
if (strlen($password) != 128) { 
    // The hashed pwd should be 128 characters long. 
    // If it's not, something really odd has happened 
    $error_msg .= '<p class="error">Invalid password configuration.</p>'; 
} 

$prep_stmt = "SELECT id FROM members WHERE email = ? LIMIT 1"; 
$stmt  = $db->prepare($prep_stmt); 

if ($stmt) { 
    $stmt->bind_param('s', $email); 
    $stmt->execute(); 
    $stmt->store_result(); 

    if ($stmt->num_rows == 1) { 
     // A user with this email address already exists 
     $error_msg .= '<p class="error">A user with this email address already exists.</p>'; 
    } 
} else { 
    $error_msg .= '<p class="error">Database error</p>'; 
} 

if ($new_password != $retype_password) { 
    // Create a random salt 
    $salt   = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), TRUE)); 
    // Create salted password 
    $new_password = hash('sha512', $random_salt . $salt); 

} 

// Insert the new hashed password into the database 
if ($insert_stmt = $db->prepare("UPDATE members SET password = ? WHERE id = ?")) { 
    $insert_stmt->bind_param('si', $new_password, $userID); 
    // Execute the prepared query. 
    if (!$insert_stmt->execute()) { 
     header('Location: ../error.php?err=Database Registration failure: INSERT'); 
     exit(); 
    } 

    // Update recovery key  
    if ($insert_stmt = $db->prepare("UPDATE recovery_keys SET valid = 0 WHERE userID = ? AND token = ? ")); 
    $insert_stmt->bind_param('is', $userID, $token); 
    // Execute the prepared query. 
    if ($insert_stmt->execute()) 
     $msg = 'Your password has changed successfully. Please login with your new password.'; 

} else { 
    $msg = "Password doesn't match"; 

    header('Location: ../error.php?err=Registration failure in updating recovery key: INSERT'); 
    exit(); 
} 

?> 

重要的事情,你需要學習適當。

更新here's the link

預處理語句:link here

密碼哈希:link here

你的散列方法是很容易的PHP並提供更好的安全方式,請按照上面的鏈接。

+0

我認爲不需要的{exit();}'會產生一個錯誤。 – Mikey

+1

@Mikey我可以看到一個錯誤的參數(它應該在每個'header('Location:...')'語句)之後,但它不會導致錯誤。 –

+0

@ChrisForrence是它的錯位。 –