我偶然发现我的登录表单有问题。当密码部分正确时,我似乎可以登录。
如果我创建以下用户:
用户名:呵呵呵呵
密码:呵呵呵呵
我可以用"呵呵"、"呵呵"1111等密码登录。如果我写错了,它就不起作用了。
登录.php
if (empty($_POST) === false) {
$username = trim($_POST['username']);
$password = trim($_POST['password']);
if (empty($username) === true || empty($password) === true) {
$errors[] = 'Sorry, but we need your username and password.';
} else if ($users->user_exists($username) === false) {
$errors[] = 'Sorry that username doesn''t exists.';
// } else if ($users->email_confirmed($username) === false) {
// $errors[] = 'Sorry, but you need to activate your account.
// Please check your email.';
} else {
if (strlen($password) > 18) {
$errors[] = 'The password should be less than 18 characters, without spacing.';
}
$login = $users->login($username, $password);
if ($login === false) {
$errors[] = 'Sorry, that username/password is invalid';
}else {
$_SESSION['id'] = $login;
header('Location: home.php');
exit();
}
}
}
User.class.php
public function login($username, $password) {
global $bcrypt;
$query = $this->db->prepare("SELECT `password`, `user_id` FROM `users` WHERE `username` = ?");
$query->bindValue(1, $username);
try{
$query->execute();
$data = $query->fetch();
$stored_password = $data['password'];
$id = $data['user_id'];
if($bcrypt->verify($password, $stored_password) === true){
return $id;
}else{
return false;
}
}catch(PDOException $e){
die($e->getMessage());
}
}
Bcrypt.class.php
class Bcrypt {
private $rounds;
public function __construct($rounds = 12) {
if(CRYPT_BLOWFISH != 1) {
throw new Exception("Bcrypt is not supported on this server, please see the following to learn more: http://php.net/crypt");
}
$this->rounds = $rounds;
}
private function genSalt() {
$string = str_shuffle(mt_rand());
$salt = uniqid($string ,true);
return $salt;
}
public function genHash($password) {
$hash = crypt($password, '$2y$' . $this->rounds . '$' . $this->genSalt());
return $hash;
}
public function verify($password, $existingHash) {
$hash = crypt($password, $existingHash);
if($hash === $existingHash) {
return true;
} else {
return false;
}
}
}
有什么想法吗?
如果你们认为这可能与注册过程有关,请告诉我,我也会上传注册代码。我不明白的是,为什么即使只是部分密码是正确的,它也能工作,我以前从未经历过这种情况。
crypt似乎使用DES进行哈希,而不是blowfish:http://php.net/manual/en/function.crypt.php
标准的基于DES的crypt()将salt作为输出的前两个字符返回。它也只使用str的前八个字符,因此以相同八个字符开头的较长字符串将生成相同的结果(当使用相同的salt时)。
尝试使用您的代码只使用前8个字符登录。
还要查看存储在数据库中的已保存哈希,看看它们是使用blowfish还是DES。如果使用河豚,它们应该有你使用的$2y$签名。