尝试使用 OO 语句登录时出现 Errno(0)
Errno(0) when attempting log in with OO statement
我正在尝试创建一个更安全的登录系统。我的注册工作正常,所以这不是连接问题。只需要一双新的眼睛看看是否有任何我可能遗漏的错误,有人可以帮忙吗?谢谢!
login.php
session_start();
if (isset($_POST['submit']))
{
$user = $_POST['username'];
$pass = $_POST['password'];
if(!($stmt = $mysqli->prepare("SELECT username, password FROM users WHERE username = ?"))){
echo "Prepare failed: (" . $mysqli->errno . ")" . $mysqli->error;
}
if(!$stmt->bind_param('s', $user)){
echo "Bind failed: (" . $stmt->errno . ")" . $stmt->error;
}
if(!$stmt->execute()){
echo "Execute failed: (" . $stmt->errno .")" . $stmt->error;
}
$userdata = $stmt->get_result();
$row = $userdata->fetch_array(MYSQLI_ASSOC);
$stmt->bind_result($user, $pass);
$stmt->store_result();
if(password_verify($pass, $row['password'])){
$_SESSION['login_user'] = $_POST['username'];
header('Location: profile.php');
exit();
}
}
else{
echo "Login Failed: (" . $stmt->errno .")" . $stmt->error;
}
$stmt->close();
$mysqli->close();
index.php(登录表单)
<div id="loginform">
Log in details<br /><br />
<form method="post" action="login.php">
Username:
<input type="text" name="username" />
<br /><br>
Password:
<input type="password" name="password" />
<br /><br>
<input type="submit" name="submit" value="Submit" />
</form>
</div>
您不应在 Login Failed
错误消息中使用 $stmt->errno
和 $stmt->error
。该行位于 if (isset($_POST['submit']))
的 else
子句中,因此它与 MySQL 错误无关。我不确定您为什么会收到该消息,因为只有当您前往 login.php
而未在 index.php
上提交登录表单时才会发生这种情况。
由于您正在使用 $userdata->fetch_array()
从数据库中获取结果行,因此您不应同时使用 $stmt->bind_result()
-- 两者兼而有之。我认为 bind_result()
没有做任何事情,因为您永远不会调用 $stmt->fetch()
来获取这些变量的行。
如果您决定使用 bind_result()
,您需要为密码使用不同的变量,因为 $pass
包含从表单提交的密码。
您需要检查查询是否返回了一行——如果用户输入了无效的用户名,则不会。所以密码检查应该是:
if ($row && password_verify($pass, $row['password']) {
...
}
然后您应该有一个 else
子句来报告用户名或密码无效。你不应该区分是用户名还是密码错误,这对安全性是不利的(这有助于暴力破解者知道他猜对了用户名,只需要尝试不同的密码)。
$stmt->close()
应该在 if
块内。
我正在尝试创建一个更安全的登录系统。我的注册工作正常,所以这不是连接问题。只需要一双新的眼睛看看是否有任何我可能遗漏的错误,有人可以帮忙吗?谢谢!
login.php
session_start();
if (isset($_POST['submit']))
{
$user = $_POST['username'];
$pass = $_POST['password'];
if(!($stmt = $mysqli->prepare("SELECT username, password FROM users WHERE username = ?"))){
echo "Prepare failed: (" . $mysqli->errno . ")" . $mysqli->error;
}
if(!$stmt->bind_param('s', $user)){
echo "Bind failed: (" . $stmt->errno . ")" . $stmt->error;
}
if(!$stmt->execute()){
echo "Execute failed: (" . $stmt->errno .")" . $stmt->error;
}
$userdata = $stmt->get_result();
$row = $userdata->fetch_array(MYSQLI_ASSOC);
$stmt->bind_result($user, $pass);
$stmt->store_result();
if(password_verify($pass, $row['password'])){
$_SESSION['login_user'] = $_POST['username'];
header('Location: profile.php');
exit();
}
}
else{
echo "Login Failed: (" . $stmt->errno .")" . $stmt->error;
}
$stmt->close();
$mysqli->close();
index.php(登录表单)
<div id="loginform">
Log in details<br /><br />
<form method="post" action="login.php">
Username:
<input type="text" name="username" />
<br /><br>
Password:
<input type="password" name="password" />
<br /><br>
<input type="submit" name="submit" value="Submit" />
</form>
</div>
您不应在 Login Failed
错误消息中使用 $stmt->errno
和 $stmt->error
。该行位于 if (isset($_POST['submit']))
的 else
子句中,因此它与 MySQL 错误无关。我不确定您为什么会收到该消息,因为只有当您前往 login.php
而未在 index.php
上提交登录表单时才会发生这种情况。
由于您正在使用 $userdata->fetch_array()
从数据库中获取结果行,因此您不应同时使用 $stmt->bind_result()
-- 两者兼而有之。我认为 bind_result()
没有做任何事情,因为您永远不会调用 $stmt->fetch()
来获取这些变量的行。
如果您决定使用 bind_result()
,您需要为密码使用不同的变量,因为 $pass
包含从表单提交的密码。
您需要检查查询是否返回了一行——如果用户输入了无效的用户名,则不会。所以密码检查应该是:
if ($row && password_verify($pass, $row['password']) {
...
}
然后您应该有一个 else
子句来报告用户名或密码无效。你不应该区分是用户名还是密码错误,这对安全性是不利的(这有助于暴力破解者知道他猜对了用户名,只需要尝试不同的密码)。
$stmt->close()
应该在 if
块内。