2016-04-21 92 views
0

如果我有一個登錄系統這個PHP腳本:使用MD5和密碼散列函數在數據庫中存儲時

$user = $_POST['user_name']; 
    $pass = md5($_POST['user_pass']); 

    require_once("connection_file.php"); 
    $sql = "SELECT * FROM login_table WHERE user_n = :us AND user_p = :password"; 
    $stmt = $conn->prepare($sql); 
    $stmt->bindValue(':us', $user, PDO::PARAM_STR); 
    $stmt->bindValue(':password', $pass, PDO::PARAM_STR); 
    $stmt->execute(); 
    $result = $stmt->fetchAll(); 
    if($result) 
    { 
     //echo $msg = "user exist"; 
     if(session_status() == PHP_SESSION_NONE) 
     { 
      session_start(); 
      foreach($result as $row) 
      { 
       $hash = password_hash($row['user_pass'], PASSWORD_BCRYPT); 
       if(password_verify($row['user_pass'], $hash)) 
       { 
        $_SESSION['userid'] = $row['user_id']; 
        $_SESSION['role'] = $row['user_role']; 
        header("Location: homepage.php"); 
       } 
      } 
     } 
    } 
    else 
    { 
     $msg = "Wrong credentials"; 
     header("Location: login_page.php"); 
    } 

正如你看到的,我已經救了我的數據庫密碼MD5,我使用$pass = md5($_POST['user_pass']);以驗證用戶輸入的文本是否等於MD5散列。

  1. 現在的問題是,我應該使用password_hashpassword_verify,因爲我使用這個腳本?或者使用MD5就夠了?

  2. 而我的第二個問題是我可以使用哈希字符串結果保存數據庫中的密碼,或者可以使用md5嗎?

+1

不要使用MD5這是一箇舊的和薄弱的散列。 – Daan

+0

但是,當我使用腳本的password_hash部分時,這是正確的嗎?爲什麼你低估了我? – androidnation

+0

我沒有downvote和是使用'password_hash' – Daan

回答

3

是的,您應該遷移到新的API並且不要立即再次使用MD5來實現此目的。


如果你不使用password_hash()/password_verify()並希望migrate your code to a more secure method, seamlessly

  1. 添加一列以您的用戶帳戶的表,稱爲legacy_password(或同等學歷)。
  2. 計算現有MD5哈希值的bcrypt哈希值並將它們存儲在數據庫中(設置爲legacy_passwordTRUE)。
  3. 修改您的驗證碼以處理遺留標誌。

當用戶嘗試登錄時,首先檢查是否設置了legacy_password標誌。如果是,則首先預先使用MD5對其密碼進行哈希處理,然後使用此預設值代替其密碼。之後,重新計算 bcrypt散列並將新散列存儲在數據庫中,禁用該過程中的legacy_password標誌。在PHP 7+非常寬鬆的例子如下:

/** 
* This is example code. Please feel free to use it for reference but don't just copy/paste it. 
* 
* @param string $username Unsafe user-supplied data: The username 
* @param string $password Unsafe user-supplied data: The password 
* @return int The primary key for that user account 
* @throws InvalidUserCredentialsException 
*/ 
public function authenticate(string $username, string $password): int 
{ 
    // Database lookup 
    $stmt = $this->db->prepare("SELECT userid, passwordhash, legacy_password FROM user_accounts WHERE username = ?"); 
    $stmt->execute([$username]); 
    $stored = $stmt->fetch(PDO::FETCH_ASSOC); 
    if (!$stored) { 
     // No such user, throw an exception 
     throw new InvalidUserCredentialsException(); 
    } 
    if ($stored['legacy_password']) { 
     // This is the legacy password upgrade code 
     if (password_verify(md5($password), $stored['passwordhash'])) { 
      $newhash = password_hash($password, PASSWORD_DEFAULT); 
      $stmt = $this->db->prepare("UPDATE user_accounts SET passwordhash = ?, legacy_password = FALSE WHERE userid = ?"); 
      $stmt->execute([$newhash, $stored['userid']]); 

      // Return the user ID (integer) 
      return $stored['userid']; 
     } 
    } elseif (password_verify($password, $stored['passwordhash'])) { 
     // This is the general purpose upgrade code e.g. if a future version of PHP upgrades to Argon2 
     if (password_needs_rehash($stored['passwordhash'], PASSWORD_DEFAULT)) { 
      $newhash = password_hash($password, PASSWORD_DEFAULT); 
      $stmt = $this->db->prepare("UPDATE user_accounts SET passwordhash = ? WHERE userid = ?"); 
      $stmt->execute([$newhash, $stored['userid']]); 
     } 
     // Return the user ID (integer) 
     return $stored['userid']; 
    } 
    // When all else fails, throw an exception 
    throw new InvalidUserCredentialsException(); 
} 

用法:

try { 
    $userid = $this->authenticate($username, $password); 
    // Update the session state 
    // Redirect to the post-authentication landing page 
} catch (InvalidUserCredentialsException $e) { 
    // Log the failure 
    // Redirect to the login form 
} 

主動升級原有哈希是在一個機會主義策略(換湯不換藥當用戶登錄安全取勝,但離開不安全在非活動用戶的數據庫中散列):使用主動策略,如果您的服務器在所有人再次登錄之前都被入侵,那麼他們的密碼已經使用了可接受的算法(在示例代碼中爲bcrypt)。

上述示例代碼也可用於Bcrypt-SHA-384的風味。


此外,這與encryption無關。

相關問題