2012-12-10 48 views
0

我需要幫助,我的登錄腳本 - 它似乎被打破。如果我沒有輸入密碼,我仍然可以正確登錄。另外如果我不輸入任何東西。但是,如果我輸入了錯誤的用戶名和密碼,它說我的登錄憑據是錯誤的。破損的PHP登錄腳本

<?php 
    $verbindung = mysql_connect("localhost", "root" , "") 
    or die("Verbindung zur Datenbank konnte nicht hergestellt werden"); 
    mysql_select_db("v1nce_website") or die ("Datenbank konnte nicht ausgewählt werden"); 

    $username = $_POST["username"]; 
    $password = $_POST["password"]; 

    $abfrage = "SELECT username, password FROM logins WHERE username='$username' LIMIT 1"; 
    $ergebnis = mysql_query($abfrage); 
    $row = mysql_fetch_object($ergebnis); 

    if($row->password == $password) 
     { 
     $_SESSION["username"] = $username; 
     echo "<p>Login erfolgreich.</p>"; 
     } 
    else 
     { 
     echo "<p>Benutzername oder Passwort waren falsch. <a href=\"index.php?p=login\">Login</a></p>"; 
     } 
?> 

任何幫助,將不勝感激。

+8

[**請不要在新代碼中使用'mysql_ *'函數**](http://bit.ly/phpmsql)。他們不再被維護,[棄用過程](http://j.mp/Rj2iVR)已經開始。看到[**紅框**](http://j.mp/Te9zIL)?學習[*準備的語句*](http://j.mp/T9hLWi),並使用[PDO](http://php.net/pdo)或[MySQLi](http://php.net/ mysqli) - [這篇文章](http://j.mp/QEx8IB)將幫助你決定哪個。如果你選擇PDO,[這裏是一個很好的教程](http://j.mp/PoWehJ)。 –

+1

如果沒有行,mysql_fetch_object返回FALSE。 $ _POST中的空白密碼也會評估爲false ...所以如果(false == false)... – GarethL

+0

請注意,您的密碼不安全!請閱讀[hash](http://php.net/manual/en/faq.passwords.php) –

回答

3

有很多的事情在這個腳本是令人擔憂的事情:

  1. 讓我們先從實際問題,你在這裏。如果您的查詢不會找到匹配的行,$row將等於false。因此,因此$row不是一個對象,$row->password將評估爲NULL。所以,如果$password是空字符串$row->password == $password將評估爲真,因爲NULL == ""是真的。

    如果您打開了錯誤顯示例如ini_set('display_errors', true);以及足夠的錯誤報告級別,例如error_reporting(E_ALL);,您將會收到通知。

    當您輸入錯誤的用戶名和密碼錯誤時,$row->password將再次爲NULL,但由於您輸入了密碼的非空字符串,此時$row->password == $password將評估爲false。

    因此,爲了緩解這個問題,您需要確保在開始比較密碼之前首先檢查是否存在匹配的行,例如先評估mysql_num_rows($ergebnis)

  2. 您的腳本容易受到SQL injection的影響。這意味着腳本的用戶在輸入SQL黑客時可能會造成傷害,因爲它們的值爲$_POST[ 'username' ]。舉例來說,如果我是進入' OR 1 = 1 --您的SQL查詢將導致以下(格式化用於顯示目的):

    SELECT username, password 
    FROM logins 
    WHERE username='' OR 1 = 1 --' LIMIT 1 
    

    ...因爲WHERE username='' OR 1 = 1總是計算爲真(SQL中的--表示評論,因此不會再評估' LIMIT 1),因此總是會導致至少一行。

    爲了緩解這一問題,在當前的設置,你需要用mysql_real_escape_string()第一淨化你的輸入值,將其傳遞到SQL查詢,例如前:

    $username = mysql_real_escape_string($_POST["username"]); 
    

    但正如其他人已經作爲建議那麼你會更聰明地開始使用MySQL兼容的庫,該庫提供參數化查詢的準備語句,如PDOMySQLi,因爲mysql_*庫正在被棄用的過程中,因爲它提供了防範SQL注入。

  3. 您的密碼以逐字(純文本)的形式存儲在數據庫中。這爲賬戶(可能與用戶相關的賬戶)受到損害提供了各種潛在風險。任何有權訪問數據庫的人(無論是直接訪問,授權訪問還是數據庫受損時)都可以以明文形式查看密碼,因此可以使用這些密碼登錄到您的網站,或將其用作潛在用戶登錄其他網站和/或服務。畢竟,人們對各種其他網站和服務使用相同的用戶名和密碼組合並不罕見。

    爲了緩解這個問題,在將密碼存儲到數據庫之前,您應該明智地對密碼進行hash(單向加密),然後,當用戶想要登錄時,將存儲的散列值與散列值進行比較再次使用相同的散列函數)用戶輸入的密碼。也強烈建議使用每個用戶密碼的獨特salt作爲額外的安全措施,因爲這可以防止所謂的rainbow table攻擊。

    有關要使用的首選散列算法的更詳盡的解釋以及爲什麼請參閱this answer by user Andrew Moorethis question

+0

真棒回答。 +100。 –

1
$abfrage = "SELECT username, password FROM logins WHERE username='$username' LIMIT 1"; 
    $ergebnis = mysql_query($abfrage); 
if(mysql_num_rows($ergebnis) > 0) // you can check for one 
{ 
    $row = mysql_fetch_object($ergebnis); 
//rest code goes inside here 
// redirect to any page or do whatever you like 
} 
+1

開頭編寫'session_start()'並且執行一件事。在獲取用戶名時使用mysql_real_escape_string,以避免sql注入。如果可能的話,遷移到pdo或mysqli_ *函數作爲manticore提到 – Dev

1

我假設你正在做登錄,以防止SQL注入,但是,mysql_real_escape_string()會很快解決這個問題。我會做這樣的事情:

$login = mysql_query("SELECT id FROM users WHERE username='" . mysql_real_escape_string($username) . "' AND password='" . mysql_real_escape_string($password) . "' LIMIT 1"); 
if (mysql_num_rows($login) > 0) { 
     $user = mysql_fetch_array($login); 
     $_SESSION['userID'] = $user['id']; 
     echo 'Login successful!'; 
} else { // login failed 
     echo 'Login failed.'; 
} 

請注意,我將用戶的ID存儲在會話中,而不是他們的用戶名。這通常是一個更好的主意,因爲基於唯一的auto_increment索引值而不是文本用戶名來管理用戶活動要容易得多。大多數網站都沒有,但是如果你願意的話,這種方法可以讓你讓多個用戶擁有相同的用戶名。但是,如果您這樣做,請確保您根據他們的電子郵件地址而不是他們的用戶名登錄他們,因爲您不希望某人以其他用戶身份登錄,因爲他們共享相同的用戶名。

此外,你應該加密密碼。 MD5是一個簡單的解決方案,可以像這樣實現:

$password = md5($_POST['password']); 

如果MD5密碼輸入,你不需要擔心斜線,無論是。希望有所幫助。

+1

允許重複的用戶名是一件很奇怪的事情。 – MrCode

+0

@MrCode Eh,Stack Overflow和其他StackExchange站點實際上允許這樣做,我相信。 ;-) –

+0

@fireeyedboy SE與大多數人不同,因爲它被視爲更多的人的名字(因此允許空格),而不是傳統上不允許空格或重複的用戶名/暱稱/句柄。 – MrCode

1

也許密碼沒有從數據庫中得到正確的。使用print_r($row)確保一切都很好。

同時使用sha1加鹽來增加安全性。也可以這樣做:

$username = mysql_real_escape_string($_POST["username"]); 
$password = mysql_real_escape_string($_POST["password"]); 

避免注射。

希望這會有所幫助。