2014-11-04 30 views
-2

已經散列明文密碼我找到了一個解決方案,以低於基準可以幫助使用PHP PDO人的問題。我測試了它,它的工作原理,但我不確定它是最乾淨的代碼還是最好的。任何改進都歡迎。的PHP 5.5的散列API和數據庫

下面是引用原題:

我想哈希那些已經在MySQL數據庫中的密碼。我已經可以使用php 5.5散列API來散列新密碼,但是我想知道是否有辦法將所有舊的純文本密碼並將其轉換爲bcrypt散列。我現在正在考慮將密碼複製到一個名爲'hash'的新行,並且在檢查它們正確複製之後,將它們轉換爲散列。但我不確定如何複製密碼行並在同一張表上重命名,或者如何最有效地對所有這些密碼進行哈希處理。

任何有識之士將不勝感激。

這裏是解決方案:

<? 
    // IMPORTANT: only call this script one time or you will double hash and the passwords input by your users won't work anymore 

    // Get Configuration file 
    require("configsecuresavedgames.php"); 

    // Connect to your server 

    $dbh = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8" , $user, $pass); 
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 


    /////////////////////////////////////////////////////// 
    // Upload new score 
    /////////////////////////////////////////////////////// 

// set variable $x to 1 to start at ID 1 and then update each row in a loop, adding 1 to the $x variable once done 

$x = 1; 
// Note: Change the statement below so that the number is larger to match the number of users in your database 

while($x <= 100) { 

// select hash for each row... 
    $stmt = $dbh->prepare("SELECT hash FROM $tname WHERE id = $x"); 
    $stmt->execute(); 

    // set the resulting array to associative 
    $result = $stmt->setFetchMode(PDO::FETCH_ASSOC); 

// set $hash variable to hash (from database) for the respective row 

    while($row = $stmt->fetch(PDO::FETCH_ASSOC)) { 
    echo $row['hash']; 
    $hash = $row ['hash']; 
} 

// update hash row with new hash data (note: prior to running the script make sure that you've copied all plain text passwords to the hash row in the database. 


    $newhash = password_hash($hash, PASSWORD_DEFAULT); 
    $sql = "UPDATE securesavegames SET hash = '$newhash' WHERE id = $x"; 


    // Prepare statement 
    $stm = $dbh->prepare($sql); 

    // execute the query 
    $stm->execute(); 

    // echo a message to say the UPDATE succeeded 
    echo $stm->rowCount() . " records UPDATED successfully"; 

    // add to $x so that the hash for the next 'id' will be updated, then the loop will continue. 

$x++; 

} 
$dbh = null; 

?> 
+0

沒有。哈希=絞肉機。哈希將牛變成漢堡。沒有辦法把漢堡包變回原來的牛。你必須讓你的用戶重新輸入他們的密碼,以便他們可以通過新的散列運行。 – 2014-11-04 14:14:27

+2

@MarcB我認爲他所指的密碼已經是純文本了。 – Flosculus 2014-11-04 14:18:37

+0

啊,對不對......在這種情況下,'更新yourtable集new_hash =散列(old_password_field)'。你可以做一個in-place'set pw = hash(pw)',但是你會失去原始的純文本。 – 2014-11-04 14:28:29

回答

1

如果你的密碼是純文本格式,只是通過他們通過哈希,你會被設定。

這裏沒有一個簡單的方法有一個查詢做你的更新,因爲password_hash是一個PHP函數。你將不得不提取值,然後通過它們循環。準備好的陳述對此有很大的幫助。

$sql = 'SELECT record_id, password FROM table'; 
$res = $mysqli->query($sql); 

$sql = 'UPDATE table SET password = ? WHERE record_id = ?'; 
$prep = $mysqli->prepare($sql); 
$prep->bind_param('si', $pass, $record); 

while($row = $res->fetch_assoc()) { 
     $pass = password_hash($row['password']); 
     $record = $row['record_id']; 
     $prep->execute(); 
} 
+0

謝謝,但如果他們已經在數據庫中,我如何通過哈希傳遞它們?是否有一個SQL查詢可以同時對所有密碼執行此操作?當用戶添加數據時,我感覺php腳本非常好,可以散列密碼,但是如何獲取數據庫中已有的內容並通過php 5.5 hashing API運行密碼?密碼是純文本的(現在還沒有散列)。 – brett 2014-11-04 17:23:14

+0

我用一個可以使用的循環更新它。沒有更簡單的方法,因爲您不能將PHP混入到這樣的INSERT SELECT語句中。如果你想打破循環,只需在你的初始查詢中添加'WHERE password NOT NOTKE「$%」',並反覆運行直到所有內容都被更新爲止 – Machavity 2014-11-04 18:18:05

+0

謝謝Machavity,但我一直在收到以下錯誤代碼,我不確定它是什麼意思:「致命錯誤:調用一個非對象的成員函數query()...」這是指什麼?謝謝, – brett 2014-11-17 04:57:23