永远不要使用该代码!
那里有一个非常严重的 SQL 注入。您获取的每个用户输入,无论是来自 cookie、CGI 还是任何地方,都必须在用于 SQL 语句之前进行清理。我可以通过尝试使用如下用户名登录来轻松闯入该系统:
user'; UPDATE contractors SET password = '1337'
... 之后我可以以任何人的身份登录。抱歉,如果我听起来很咄咄逼人,但该代码的作用就像忘记将前门锁在您的公司内,它可能甚至不包含警报系统。
请注意,输入是否真的来自用户并不重要(也许它是在预填充的,隐藏的)。从安全的角度来看,来自外部任何地方的任何东西都必须被视为包含用户的恶意输入。
据我所知,您需要使用 PDO 的 quote 函数来正确清理字符串。 (在 mysql 中,这将通过 mysql_real_escape_string() 完成。)我不是 PDO 方面的专家,请注意,如果我在这里错了,请有人纠正。
另外,您可能不应该将任何密码直接存储在数据库中,而是使用哈希函数创建一个掩码密码,然后从用户提供的密码创建一个哈希,并匹配哈希。您可以使用 PHP hash 函数来执行此操作。
至于其他问题,我不知道您在 SQL SELECT 上的方法是否是最好的方法。我只需选择相应用户的密码并尝试在程序中匹配它。我认为您使用的方法也没有任何错误,但它似乎不合逻辑,因此 me 错过一些错误的可能性更大 - 如果密码和登录名会为漏洞创建一个窗口。
要按照自己的方式进行操作,您需要注意您从PDO query 获得的结果是PDOStatement,这似乎没有可靠的函数来直接计算结果的数量行。您需要使用的是fetchAll,它返回一个行数组,并计算它。然而,正如我所说,这一切对我来说都像是对失败开放,所以我会觉得检查代码中的密码更安全。在这样一个对安全至关重要的地方,与实际密码匹配的距离太远了。
因此,要获取用户 ID 的最终密码,您可以使用 PDOStatement 的 fetch() 从结果中返回列的内容。例如,使用 PDO::FETCH_ASSOC 根据列名将它们放入关联数组中。
解决方法如下:
$userid_dirty = $_POST['userid'];
$password_dirty = $_POST['pass'];
$success = false; // This is to make it more clear what the result is at the end
if ($userid != "" || $password != "") {
$userid = $dbh->quote($userid_dirty);
$passwordhash = hash('sha256',$password_dirty);
$sql = "SELECT userid, passwordhash, company, security_id FROM contractors WHERE userid = ".$userid;
$result = $dbh->query( $sql );
if ($result) { // Check if result not empty, that userid exists
$result_array = $result->fetch(PDO::FETCH_ASSOC);
if ($result_array['PASSWORDHASH'] == $passwordhash) {
// login success
$success = true;
// do all the login stuff here...
// such as saving $result_array['USERID'], $result_array['COMPANY'], $result_array['SECURITY_ID'] etc.
} // else fail, wrong password
} // else fail, no such user
} else {
// fail, userid or password missing
echo ' please enter user id and password.';
}
if (!$success) {
echo ' login failed.';
}
当然,代码可以稍微清理一下,但这应该说明需要做什么。请注意,由于密码都是散列的,并且 从未在 SQL 中使用,因此它实际上不需要清理。但我把它留在那里以防万一,因为在原始代码中它在查询中使用。
请注意,所有有关存储密码的代码都需要更改为存储哈希而不是密码。此外,在散列之前使用添加到密码的salt 是一个非常好的主意。
另外,我提供代码只是为了教育目的 - 我只是认为代码是解释如何做到这一点的最清晰的方式。所以不要把这个网站误认为是请求代码的服务。 :)