我的问题是,当我尝试登录时,我的脚本直接跳到循环的else部分。我尝试放入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)
因此,我的查询不会返回任何内容。
因此,我通过将$table变量删除为确切的表名"members“来更改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行是我的if($count==1)
因此,我对数据库测试了一个简单的查询
SELECT * From members结果是,显示了第0.0004 -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 0.0007 2. mysql_num_rows() /var/www/ideabank/checklogin.php:35 NULL
当警告执行时,第35行有一个错误,返回NULL!
创建警告的行是my counter,它的存在是为了确保只显示一条记录。
我最初的想法是,
如果结果与$username & $password匹配,则行必须为==到1
但是它抛出了相同的sql错误
现在,我尝试更改计数器,改为使用mysql_num_rows
if (
mysql_num_rows($result))
{
session_start();
...
eller
if (
mysql_num_rows($result) == 1)
{
session_start();
...但它仍然会抛出sql警告。
发布于 2011-07-29 01:34:46
由于您使用的是sha512,因此应该将password字段的类型更改为varchar(512),否则在写入数据库时,您的密码将被截断为256个字符。
发布于 2011-07-29 01:13:22
Try:$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变量!您可能无法获得发布的username password变量...第二个不会立即引起注意,因为散列算法会将一个空白字符串转换为其他字符串。
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?username=me&password=1234),有时还允许$_COOKIE {取决于php.ini设置}
样式更改
你可以说:
,这是正确的,因为我有两个帐户使用相同的密码。
您可能需要考虑对散列过程进行唯一加盐处理,这样具有相同密码的任何两个用户在数据库中都不会具有相同的散列值。要做到这一点,最简单的方法是使用用户名(已经是一个方便的唯一值),您可以先对其进行一次散列(尽管这是否提供了好处尚有争议)。因为它是站立的,所以可以在您的数据库上使用rainbow table攻击。
第二个风格是关于如何检查用户名/密码。我将使用SQL来提取用户的记录(如果他们不是用户,则为none ),然后使用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()等),它们应该为用户提供更具体的消息(例如,“您的帐号已过期”)基础工作已经完成。
发布于 2011-07-29 01:16:56
首先检查mysql_query()的返回值
if( mysql_query($query) ) {
// retrieve result
}
else {
die( mysql_error() );
}阅读有关SQL注入漏洞以及如何在PHP中预防它们的文章。你的代码是一个等待发生的安全噩梦。首先,通过mysql_real_escape_string()运行用户名和密码。或者更好的做法是使用PDO,它为您提供了占位符。
不要使用session_register()
https://stackoverflow.com/questions/6862851
复制相似问题