2

我正在尝试建立一个更安全的登录系统。我的注册工作正常,所以它不是连接问题。只需要一双新的眼睛,看看是否有任何我可能遗漏的错误,有人可以帮忙吗?谢谢!

登录.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>
4

1 回答 1

3

您不应该在错误消息中使用$stmt->errnoand 。该行位于for 子句中,因此与 MySQL 错误无关。我不确定您为什么会收到该消息,因为只有在您没有提交登录表单的情况下才会发生这种情况。$stmt->errorLogin Failedelseif (isset($_POST['submit']))login.phpindex.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块内。

于 2015-12-19T16:38:24.587 回答