我在这里看到类似的问题,但我不认为答案适用于我,如果他们这样做我很抱歉..
下面是包含两个过程的代码片段:
注意:登录和注册完全正常,没有散列元素。
if (isset($_POST['username']) && ($_POST['password'])) {
$username = trim($_POST['username']);
$username = strtolower($username);
$password = trim($_POST['password']);
$salt = hash('md5', "$username");
$password = hash('sha256', "$password"."$salt");
$stmt = $dbh->prepare("SELECT `id` FROM `1_users` WHERE username=? AND password=? LIMIT 1");
$stmt->bindValue(1, $username, PDO::PARAM_STR);
$stmt->bindValue(2, $password, PDO::PARAM_STR);
$stmt->execute();
if ($stmt->rowCount()) {
// Match
$results = $stmt->fetch(PDO::FETCH_ASSOC);
$_SESSION['id'] = $results['id'];
$_SESSION['logged_in'] = true;
$_SESSION['ip'] = hash('sha1', "{$_SERVER['REMOTE_ADDR']}");
header ("location: account.php");
}
else {
$error = 'Invalid username/password!';
}
}
if (isset($_POST['register'])) {
// check for all fields..
if ((empty($_POST['r_username'])) || (empty($_POST['r_password'])) || (empty($_POST['re_password'])) || (empty($_POST['email']))) {
$r_error = 'One of the fields was empty.';
}
$stmt = $dbh->prepare("SELECT `username` FROM `1_members` WHERE `username`=? LIMIT 1");
$username = strtolower($_POST['r_username']);
$username = trim($username);
$stmt->bindValue(1, $username, PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->rowCount();
if ($row) {
$r_error = 'that username is already in use';
}
else if (($_POST['r_password']) !== ($_POST['re_password'])) {
$r_error = 'The passwords did not match.';
}
else if (strlen($_POST['r_username']) <= '3') {
$r_error = 'username too short - needs to be 4 more charicters.';
}
else if (strlen($_POST['r_password']) <='5'){
$r_error = 'password not long enough, please make it 6-255 charicters or more.';
}
else {
// woohoo lets make the account
$password = trim($_POST['r_password']);
$salt = hash('md5', "$username");
$password = hash('sha256', "$password"."$salt");
$email = trim($_POST['email']);
$stmt = $dbh->prepare("INSERT INTO `1_members` (`username`, `password`, `email`) VALUES(?,?,?)");
$stmt->bindValue(1,$username,PDO::PARAM_STR);
$stmt->bindValue(2,$password,PDO::PARAM_STR);
$stmt->bindValue(3,$email,PDO::PARAM_STR);
$stmt->execute();
$_SESSION['id'] = $dbh->lastInsertId();
$_SESSION['logged_in'] = true;
$_SESSION['ip'] = hash('sha1', "{$_SERVER['REMOTE_ADDR']}");
if ($_SESSION['active_cart']) {
header ("location: cart.php");
}
else {
header ("location: account.php");
}
}
}
在将哈希添加到密码之前,它正常运行,我不确定我的问题是什么。
调试:
username: admin1
password: admin1
登录程序将密码转为:927364bb72cee168bd52c45a5d131b5923e2926eb6e8f0f46d6d7e5765cc3401
注册程序创建密码为:
927364bb72cee168bd52c45a5d131b5923e2926eb6e8f0f46d6d7e5765cc3401
他们匹配所以出了什么问题?
此外,如果我在这里有错误的想法,或者如果我忽略了重要的安全措施,请告知更好的方法。
另外,我并不那么担心电子邮件验证,而且我完全清楚有很多预制的snipplet可用于验证电子邮件,我将在以后进行此操作。
任何CC都非常受欢迎。
编辑:该脚本返回“无效的用户名/密码组合”。
答案 0 :(得分:1)
我怀疑散列密码的数据库字段太小,该字段必须能够存储64个字符。
即使您可以解决此问题,您也有一个不安全的方案来存储密码(SHA256对于散列密码来说太快了)。看看PHP函数password_hash(),它将生成一个BCrypt哈希并负责生成安全盐。盐将成为生成的62个字符串的一部分,因此无需单独存储盐。对于较旧的PHP版本,还存在compatibility pack。
// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);
// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);
这也意味着您无法直接在SQL语句中验证密码,而是从数据库中读取哈希值(通过用户名),然后使用此哈希值调用password_verify()。
答案 1 :(得分:0)
可能是,PDOStatement :: rowCount()在SELECT查询上执行时不会返回“1”。看看这里:
http://www.php.net/manual/en/pdostatement.rowcount.php
(特别是实施例#2)