2011-07-28 196 views
1

我的問題是,當我嘗試登錄時,我的腳本跳到我的循環的其他部分。 我試圖把printf語句進行調試,並發現我的密碼哈希值與數據庫中的值一致。登錄系統不能登錄

<?php 
//include_once './bin/configDb.php'; 
//MySQL connection variables 
$dbhost = 'localhost'; 
$dbname = 'ideabank'; 
$dbuser = 'xxx'; 
$dbpass = 'xxx'; 
$table = 'members'; 
// Connect to server and select databse. 
//include_once './bin/connectDb.php'; 
$conn = mysql_connect($dbhost, $dbuser, $dbpass); 
mysql_select_db($dbname, $conn); 
// username and password sent from form, cleanout, esacpe string against sqlinj. 
$username = mysql_real_escape_string($_POST['username']); 
$password = hash('sha512', $_POST['password']); 
printf("$username \n"); 
printf("$password \n"); 
$sql = "SELECT * FROM $table WHERE username = '$username' AND password = '$password' 
"; 
$result=mysql_query($sql); 
//$result = mysql_query("SELECT * FROM $table WHERE username = '$username' AND password = '$password' 
//"); 
// Replace counting function based on database you are using. 
$count=mysql_num_rows($result); 
// If result matched $username and $password, table row must be 1 row 
if($count==1){ 
// Register $username, $password and redirect to file "login_success.php" 
session_register("username"); 
session_register("password"); 
header("location:login_success.php"); 
} 
else { 
echo "Wrong Username or Password"; 
} 
exit() 
?> 

我的MySQL數據庫是這樣的,

CREATE TABLE IF NOT EXISTS `members` (
`id` int(11) NOT NULL AUTO_INCREMENT, 
`username` varchar(30) NOT NULL, 
`password` varchar(256) NOT NULL, 
PRIMARY KEY (`id`), 
UNIQUE KEY `username` (`username`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; 

我加入這個以獲得更多的錯誤信息

var_dump($count); 

而且也與我的查詢字符串試驗

$sql = "SELECT * FROM $table WHERE username = '$username'"; 

哪給了我是價值

$ SQLINT(0)

所以我的查詢不返回任何東西。

所以我通過刪除$表變量的確切的表名稱已更改SQL查詢「成員」

它給了我一個新的錯誤:

$sql Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in  
/var/www/ideabank/checklogin.php on line 35 Call Stack: 0.0002 657184 1. {main}() /var/www/ideabank/checklogin.php:0 0.0006 660584 2. mysql_num_rows() /var/www/ideabank /checklogin.php:35 NULL 

和35行是我的,如果( $計數== 1)

所以我測試一個簡單的查詢對數據庫

SELECT * From members 

其結果是,顯示行0 - 5(6總計,查詢花費0.0004秒)

好了,我再次改變該查詢那些

$sql = "SELECT * FROM members WHERE password = '$password'"; 

結果:

$ SQLINT(2)

這是正確的,因爲我有兩個帳戶具有相同的密碼。

所以我做了另一個查詢

$sql = "SELECT * FROM members WHERE username = '$username'"; 

這將使意義,因爲用戶名是唯一

結果:

$ SQL警告:mysql_num_rows()預計參數1是資源,布爾給定在/var/www/ideabank/checklogin.php在線35調用堆棧:0.0002 653256 1. {main}()/var/www/ideabank/checklogin.php:0 0.0007 656528 2. mysql_num_rows()/ var/www/ideabank/checklogin.php:35 NULL

由於warnng emplies在第35行有一個錯誤,返回NULL!

創建警告的那一行是我的計數器,它確保只顯示一條記錄。

我最初的想法是,

如果結果匹配$的用戶名& $密碼,然後行必須== 1

但它拋出同樣的SQL錯誤

現在我試圖改變櫃檯和使用mysql_num_rows代替

if (
mysql_num_rows($result)) 
{ 
session_start(); 
... 
eller 
if (
mysql_num_rows($result) == 1) 
{ 
session_start(); 
... 

但它仍然拋出了SQL警告。

回答

0

由於您使用sha512,你應該password字段的類型更改爲varchar(512),否則你的密碼將在256個字符寫入數據庫時​​被截斷。

+0

哈哈哈,我是一個多麼愚蠢。感謝你們所有人的美麗。 我的varchar設置爲128,這是一個愚蠢的錯誤:) 親愛的CFEAK&MARC B隨意添加更多的SQL注入,xss meassurements,所以我可以得到那部分直:) –

0

a)session_register()已被棄用,應該不惜一切代價避免。改爲使用$_SESSION['varname'] = $varvalue。同樣,請確保你已經完成了session_start()

b)你收到的數據庫錯誤表明你的查詢字符串有錯誤。您沒有任何錯誤代碼處理,所以更改所有的數據庫查詢來電:

$result = mysql_query($sql) or die($sql . "<br>" . mysql_error()); 

這會在錯誤發生點中止腳本,顯示你的查詢字符串,什麼確切的錯誤是。

+0

我已經添加了a)和b) 我仍然被重定向回到我來自的地方。這將是我的循環的其他部分 –

1

嘗試:$result=mysql_query($sql,$conn);(當進行查詢時,您需要指定使用哪個連接)。

當SELECT語句的mysql_query成功時,它會返回一個資源,當它失敗時它將返回false(一個布爾值 - 正是mysql_num_rows所抱怨的)。在詢問行信息之前,您應該確保mysql_query部分成功。

具體讓我們添加一些錯誤醒目碼(用於開發目的不僅沒有用於生產 - 沒有人希望看到一個die語句中使用網站時 - 生產應顯示一個漂亮的,可能遠不如描述性消息):

if (!$conn = mysql_connect($dbhost, $dbuser, $dbpass)) { 
    //This is a horrible idea in production but shows you the failure 
    // while you're coding 
    die ("Failed to connect to DB."); 
} 
if (!mysql_select_db($dbname, $conn)) { 
    //Still a bad idea! 
    die ("Unable to select DB $dbname"); 
} 

/* ... */ 

if (!$result=mysql_query($sql,$conn)) { 
    //Still bad! 
    die ("Unable to execute $sql"); 
} 

POST變量:

您應該檢查POST變量!你可能沒有得到一個usernamepassword變量發佈...第二個不會馬上引人注目,因爲散列算法會將空白字符串切換爲靜態字符串。

print_r($_POST); //Make sure you see username/password here 

或者更好的是:

if ($_POST['username']=="") { 
    //Report username is required 
} elseif ($_POST["password"]=="") { 
    //Report password is required 
} 

你也可以考慮$_REQUEST超全局這也將使$ _ GET變量(test.php的?用戶名=我&密碼= 1234),有時_COOKIE $ {取決於php.ini設置}

風格變化

你說:

Which is correct since i have two accounts with the same password.

你可能要考慮獨特醃製的hasing過程使得具有相同密碼的任何兩個用戶在db中的哈希值不會相同。最簡單的方法是使用用戶名(一個方便的唯一值),你可以先進行一次散列(儘管這是否有益處是有爭議的)。因爲它可以在你的數據庫上使用一個rainbow table攻擊。

第二種方式是關於如何檢查用戶名/密碼。我會使用SQL拉用戶的記錄(或根本沒有,如果他們不是用戶),然後用PHP來比較的密碼,因此該腳本將是:

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

//First lookup the user 
$sql="SELECT username,password FROM members WHERE username='$username'"; 
if (!$result=mysql_query($sql,$conn)) { 
    echo "Username or password is invalid."; 
    exit(); 
    //In truth username not found - for testing you could be 
    // more specific, or perhaps log the event internally: 
} 

$user=mysql_fetch_assoc($result); 
//Assumes only one user can ever match, well more accurately will only 
// access the first user ever found. (Reasonable since your user-create 
// process would filter duplicate usernames, or perhaps a members.UNIQUEKEY 

//Following will only work if you change the way passwords are stored 

define("SITESALT","NaCL"); //Should likely be defined in a header library 
// (since other pages like account-creation will require it) 
if ($user["password"]!= 
    hash('sha512',$user["username"].SITESALT.$_POST["password"])) { 
    echo "Username or password is invalid."; 
    exit(); 
    //In truth password is incorrect - might want to log. 
} 

/* //Alternate based on your existing pwd storage 
    if ($user["password"]!=hash('sha512',$_POST["password"])) { 
    echo "Username or password is invalid."; 
    exit(); 
    }*/ 

header("location:login_succes.php"); 

上面的一個方便的好處如果你添加了其他應該在登錄時驗證的用戶屬性(例如enabled = 1,expires> = now()等),它應該爲用戶提供更具體的消息(例如「你的帳戶已過期」),地面工作是已經奠定。

+0

好吧,所以你首先解決的是一個明顯的booboo,我已經修復它。我的查詢字符串現在有一個指定的連接使用。 其次,我在連接部分添加了錯誤處理,並且它不返回錯誤。要進一步檢查,我在密碼中做了一個typ0,並且確實返回了一個錯誤。所以我認爲我的連接到MySQL我好。 –

+0

然後,我在查詢部分添加了錯誤處理,看起來像這樣, $ result = mysql_query($ sql,$ conn)或者死亡($ sql。「
」。mysql_error())。 –

+0

@約翰尼爾森 - 和?成功? – Rudu

1

開始通過檢查SQL注入漏洞以及如何防止它們在PHP閱讀起來mysql_query()

if(mysql_query($query)) { 
    // retrieve result 
} 
else { 
    die(mysql_error()); 
} 

的返回值。你的代碼是一個等待發生的安全噩夢。從mysql_real_escape_string()開始運行用戶名和密碼。或更好地使用PDO,它給你佔位符。

不要使用session_register()

+0

我同意你的意見。稍後我將在後面添加anti-sqlinj屬性,如escape_string。但現在,這將是很好的基本原則排序:) –