2015-01-02 133 views
2

我測試了不同的密碼加密方式,除了我對使用的腳本的password_verify函數感到困惑之外,我已經使用了大多數方法,以及如何在腳本中實現它(請參見下文) 。該腳本涉及註冊和登錄等。該腳本成功使用下面這行代碼散列密碼。password_verify - 密碼散列

$passwordhash = password_hash($p, PASSWORD_DEFAULT); 

(從註冊)

,但是當我嘗試使用我的登錄腳本密碼,以覈實這是行不通的。所以我的問題是我如何在下面的代碼中使用password_verify函數。

<?php 
//this is executed on another page 
if(isset($_POST["e"])){ 
    // Connect to db 
    include_once("databaseconnection.php"); 
    //gather posted and sanitize 
    $e = mysqli_real_escape_string($db_conx, $_POST['e']); 
    $p = ($_POST['p']); 
    //user ip 
    $ip = preg_replace('#[^0-9.]#', '', getenv('REMOTE_ADDR')); 
    // FORM DATA ERROR HANDLING 
    if($e == "" || $p == ""){ 
     echo "login_failed"; 
     exit(); 
    } else { 
    //data error handling end 
     $sql = "SELECT id, username, password FROM users WHERE email='$e' AND activated='1' LIMIT 1"; 
     $query = mysqli_query($db_conx, $sql); 
     $row = mysqli_fetch_row($query); 
     $db_id = $row[0]; 
     $db_username = $row[1]; 
     $db_pass_str = $row[2]; 
     if($p != $db_pass_str){ 
      echo "login_failed"; 
      exit(); 
     } else { 
      //create session cookies 
      $_SESSION['userid'] = $db_id; 
      $_SESSION['username'] = $db_username; 
      $_SESSION['password'] = $db_pass_str; 
      setcookie("id", $db_id, strtotime('+30 days'), "/", "", "", TRUE); 
      setcookie("user", $db_username, strtotime('+30 days'), "/", "", "", TRUE); 
      setcookie("pass", $db_pass_str, strtotime('+30 days'), "/", "", "", TRUE); 
      //update certain fields ip, last login time 
      $sql = "UPDATE users SET ip='$ip', lastlogin=now() WHERE username='$db_username' LIMIT 1"; 
      $query = mysqli_query($db_conx, $sql); 
      echo $db_username; 
      exit(); 
     } 
    } 
    exit(); 
} 
?> 

(我試過了,失敗了,與此代碼使用password_verify funcion)

$p = password_verify($_POST['p'], $passwordhash); 

很抱歉,如果這是很難理解,但它會很感激,如果我有人可以幫助: - )

+0

password_verify函數將返回一個布爾值。如果條件檢查語句爲真,您需要使用 –

+0

您的代碼容易受到[Second Order SQLi](https://haiderm.com/second-order-sql-injection-explained-example/)的影響。始終使用參數而不是'mysqli_real_escape_string',因爲從長遠來看,您會發現它更容易。 – SilverlightFox

回答

3

假設您存儲在數據庫中的密碼已被散列化,您的問題在於您無法驗證密碼,因爲您正在比較純文本密碼和散列代碼。

我相信改變

if($p != $db_pass_str){ 
     echo "login_failed"; 
     exit(); 
    } 

if(!password_verify($p, $db_pass_str)) { 
     echo "login_failed"; 
     exit(); 
} 

應該解決您的問題,看看在password_hashpassword_verify

+0

我的數據庫中的密碼已成功散列。有了上面的代碼,我應該改變行$ p =($ _POST ['p']);還是應該讓它保持不變?謝謝你的幫助。 –

+0

保持不變,$ p = $ _POST ['p']只是將通過瀏覽器發送的密碼分配給一個變量。所以你希望它相同,然後使用密碼驗證內部檢查,以查看明文密碼的散列是否與提供的散列匹配。 –

0

你有這樣的:

$ p =($ _POST ['p']);

但後來什麼也不做這個之前,改變$ P:(!$ P = $ db_pass_str)

如果{什麼是典型的

思考,這是非典型的哈希做客戶端和非典型的數據庫以純文本存儲密碼,所以我最好的猜測是表單傳遞一個非哈希密碼和數據庫存儲哈希密碼。除非您要在登錄表單中輸入密碼哈希值,否則導致第二條引用線失敗。

如果這不是問題,那麼可能會發布一些額外的上下文。

+0

我明白你的意思了。使用md5和sha1稍微容易一些(但不太安全)。我通常只需添加md5就可以了,例如$ p = md5($ _ POST ['p']);但是使用password_verify很難以這種方式來翻譯它,因爲我不能只將password_verify作爲md5的前面。 $ p = password_verify($ _ POST ['p']);將無法工作。 –