PDO登录错误,如果($this->data()->password === Hash::make($password,


PDO login error, if ($this->data()->password === Hash::make($password, $this->data()->salt)) { always return error

我正在尝试使用PDO创建一个PHP登录/注册系统。寄存器部分工作正常,但是,当我尝试登录时,我总是收到一个错误,告诉我密码无效,即使它是正确的密码。

我将在这里添加一些脚本,并在下面进行更多解释。

注册.php:

    <?php
    require_once 'core/init.php';
    $user = new User();
    if ($user->isLoggedIn()) {
        Redirect::to('index.php');
    }
    ?>
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Register</title>
        <link rel="icon" href="favicon.ico" type="image/x-icon">
        <link rel="stylesheet" href="style/global.css">
        <script src="js/main.js"></script>
    </head>
    <body>
        <input type="checkbox" id="toggle-left">
        <input type="checkbox" id="toggle-right">
        <div class="page-wrap">
            <?php require_once 'includes/header.php'; ?>
            <?php require_once 'includes/navbar.php'; ?>
            <?php require_once 'includes/profilebar.php'; ?>
            <div class="page-content">
                <form action="" method="post">
                    <h1>Register new account</h1>
                    <div class="inset">
                    <?php
                        if(Input::exists()) {
                            if (Token::check(Input::get('token'))) {
                                $validate = new Validate();
                                $validation = $validate->check($_POST, array(
                                    'username' => array(
                                        'required' => true,
                                        'min' => 3,
                                        'max' => 200,
                                        'first_not_numeric' => true,
                                        'unique' => 'users',
                                        'alias' => 'Username'
                                    ),
                                    'password' => array(
                                        'required' => true,
                                        'min' => 6,
                                        'alias' => 'Password'
                                    ),
                                    'password_again' => array(
                                        'alias' => 'Password confirmation', // <--- using the alias
                                        'required' => true,
                                        'matches' => 'password'
                                    ),
                                    'email' => array(
                                        'required' => true,
                                        'min' => 5,
                                        'max' => 200,
                                        'email' => true,
                                        'unique' => 'users',
                                        'alias' => 'Email'
                                    ),
                                    'first_name' => array(
                                        'max' => 100,
                                        'alias' => 'First name'
                                    ),
                                    'last_name' => array(
                                        'max' => 100,
                                        'alias' => 'Last name'
                                    ),
                                    'gender' => array(
                                        'required' => true,
                                        'alias' => 'Gender'
                                    )
                                ));
                                if ($validation->passed()) {
                                    $user = new User();
                                    $salt = Hash::salt(100);
                                    $k1 = hash('sha256', Input::get('email'));
                                    $k2 = hash('sha256', mt_rand(10000,99999).time().Input::get('email'));
                                    $k3 = hash('sha256', mt_rand(100000,999999).time().Input::get('username'));
                                    try {
                                        $user->create(array(
                                            'username' => Input::get('username'),
                                            'password' => Hash::make(Input::get('password'), $salt),
                                            'salt' => $salt,
                                            'email' => Input::get('email'),
                                            'email_code' => Input::get('email_code'),
                                            'k1' => $k1,
                                            'k2' => $k2,
                                            'k3' => $k3,
                                            'first_name' => Input::get('first_name'),
                                            'last_name' => Input::get('last_name'),
                                            'gender' => Input::get('gender'),
                                            'avatar' => $user->defaultProfilePic(),
                                            'joined' => date('Y-m-d H:i:s'),
                                            'group' => 1
                                        ));
                                        if (!file_exists("users/Input::get('username')")) {
                                            mkdir('users/'.Input::get('username'), 0755);
                                        }
                                        User::sendActivation(Input::get('email'), 'Email verification', 'Hello, '.Input::get('username').',
                                        <br>
                                        Please activate your account!<br>
                                        <a href="http://www.soldiersofwar.esy.es/activate.php?k1='.$k1.'&email_code='.Input::get('email_code').'&k2='.$k2.' &k3='.$k3.'">Click here to activate your account!</a>
                                        <br><br>
                                        Copy and paste this link if the one above doesn''t work.<br>
                                        http://www.soldiersofwar.esy.es/activate.php?k1='.$k1.'&email_code='.Input::get('email_code').'&k2='.$k2.' &k3='.$k3.'
                                        <br>
                                        Thank you very much,<br>
                                        Soldiers Of War Staff');
                                        Session::flash('home', 'Please activate your account!');
                                        Redirect::to('index.php');
                                    } catch(Exception $e) {
                                        die($e->getMessage());
                                    }
                                } else {
                                    foreach ($validation->errors() as $error) {
                                        echo '<i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp;', $error, '<br />';
                                        echo '<br />';
                                    }
                                }
                            }
                        }
                    ?>
                    <!-- Username -->
                    <div>
                        <label for="username">USERNAME</label>
                        <input type="text" name="username" id="username" value="<?php echo escape(Input::get('username')); ?>" required>
                    </div>
                    <!-- Password -->
                    <div>
                        <label for="password">ENTER A PASSWORD</label>
                        <input type="password" name="password" id="password" required>
                    </div>
                    <!-- Confirm Password -->
                    <div>
                        <label for="password_again">CONFIRM PASSWORD</label>
                        <input type="password" name="password_again" id="password_again" required>
                    </div>
                    <!-- Email Address -->
                    <div>
                        <label for="email">EMAIL ADDRESS</label>
                        <input type="email" name="email" id="email" value="<?php echo escape(Input::get('email')); ?>" required>
                    </div>
                    <!-- First Name -->
                    <div>
                        <label for="first_name">FIRST NAME</label>
                        <input type="text" name="first_name" id="first_name" value="<?php echo escape(Input::get('first_name')); ?>">
                    </div>
                    <!-- Last Name -->
                    <div>
                        <label for="last_name">LAST NAME</label>
                        <input type="text" name="last_name" id="last_name" value="<?php echo escape(Input::get('last_name')); ?>">
                    </div>
                    <!-- Gender -->
                    <div>
                        <label for="gender">GENDER</label>
                        <select class="gender" id="gender" name="gender" required>
                            <option value="">Select Gender:</option>
                            <option value="Male">Male</option>
                            <option value="Female">Female</option>
                        </select>
                    </div>
                    </div>
                    <!-- Token -->
                    <input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
                    <!-- Activation -->
                    <input type="hidden" name="email_code" value="<?php echo md5('username' + microtime()); ?>" />
                    <!-- Submit button -->
                    <p class="p-container">
                        <input type="submit" name="go" id="go" value="Register new account">
                    </p>
                </form>
            </div>
            <?php require_once 'includes/footer.php'; ?>
        </div>
    </body>
    </html>

登录.php:

    <?php
    require_once 'core/init.php';
    $user = new User();
    if ($user->isLoggedIn()) {
        Redirect::to('index.php');
    }
    ?>
    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Log in</title>
        <link rel="icon" href="favicon.ico" type="image/x-icon">
        <link rel="stylesheet" href="style/global.css">
        <script src="js/jQuery.js"></script>
        <script src="js/main.js"></script>
    </head>
    <body>  
        <input type="checkbox" id="toggle-left">
        <input type="checkbox" id="toggle-right">
        <div class="page-wrap">
            <?php require_once 'includes/header.php'; ?>
            <?php require_once 'includes/navbar.php'; ?>
            <?php require_once 'includes/profilebar.php'; ?>
            <div class="page-content">
                <form action="" method="post">
                    <h1>Log in</h1>
                    <div class="inset">
                    <?php
                    if (Input::exists()) {
                        if (Token::check(Input::get('token'))) {
                            $validate = new Validate();
                            $validation = $validate->check($_POST, array(
                                'username' => array(
                                    'required' => true,
                                    'alias' => 'Username'
                                ),
                                'password' => array(
                                    'required' => true,
                                    'alias' => 'Password'
                                )
                            ));
                            if ($validation->passed()) {
                                $user = new User();
                                $remember = (Input::get('remember') === 'on') ? true : false;
                                $login = $user->login(Input::get('username'), Input::get('password'), $remember, $validate);
                                if ($login) {
                                    Redirect::to('index.php');
                                } else {
                                    foreach ($validation->errors() as $error) {
                                        echo '<i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp;', $error, '<br>';
                                        echo '<br />';
                                        //echo '<pre>', print_r($validation->errors()), '</pre>';
                                    }
                                    /*$errors = $validate->errors();
                                    if(count($errors)>0){
                                         var_dump($errors);
                                    }*/
                                }
                            } else {
                                foreach ($validation->errors() as $error) {
                                    echo '<i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp;', $error, '<br>';
                                    echo '<br />';
                                    //echo '<pre>', print_r($validation->errors()), '</pre>';
                                }
                                /*$errors = $validate->errors();
                                if(count($errors)>0){
                                     var_dump($errors);
                                }*/
                            } 
                        }
                    }
                    if(Session::exists('login')) {
                        echo '<p><i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp;' . Session::flash('login') . '</p><br />';
                    }
                    ?>
                    <p>
                        <label for="username">USERNAME</label>
                        <input type="text" name="username" id="username" value="<?php echo escape(Input::get('username')); ?>">
                    </p>
                        <!--<?php
                        /*if(isset($validation) && !$validation->passed()){
                            foreach($validation->errors() as $error){
                                if ($error->alias = 'Username') {
                                    echo '<i class="fa fa-exclamation-triangle"></i>&nbsp;&nbsp;', $error, '<br>';
                                    echo '<br />';
                                }
                            }
                        }*/
                        ?>-->
                    <p>
                        <label for="password">PASSWORD</label>
                        <input type="password" name="password" id="password">
                    </p>
                    <p>
                        <input type="checkbox" name="remember" id="remember">
                        <label for="remember">Remember me for 1 month</label>
                    </p>
                    </div>
                    <input type="hidden" name="token" value="<?php echo Token::generate(); ?>">
                    <p class="p-container">
                        <span>Forgot password?</span>
                        <span>Resend activation email</span>
                        <input type="submit" name="go" id="go" value="Log in">
                    </p>
                </form>
            </div>
            <?php require_once 'includes/footer.php'; ?>
        </div>
    </body>
    </html>

用户类中的登录功能:

    public function login($username = null, $password = null, $remember = false, $validate = null) {
        if (!$username && !$password && $this->exists()) {
            Session::put($this->_sessionName, $this->data()->id);
        } else {
            $user = $this->find($username);
            if ($user) {
                if ($this->data()->password === Hash::make($password, $this->data()->salt)) {
                    if (1 === intval($this->data()->activated)) { 
                        Session::put($this->_sessionName, $this->data()->id);
                        if ($remember) {
                            $hash = Hash::unique();
                            $hashCheck = $this->_db->get('users_session', array('user_id', '=', $this->data()->id));
                            if (!$hashCheck->count()) {
                                $this->_db->insert('users_session', array(
                                    'user_id' => $this->data()->id,
                                    'hash' => $hash
                                ));
                            } else {
                                $hash = $hashCheck->first()->hash;
                            }
                            Cookie::put($this->_cookieName, $hash, Config::get('remember/cookie_expiry'));
                        }
                        return true;
                    } else {
                        $validate->addError('You need to activate your account before you login!');
                    }               
                } else {
                    $validate->addError('Invalid password!');
                }
            } else {
                $validate->addError('That username does not exist!');
            }
        }
        return false;
    }

哈希类:

    <?php
    class Hash {
        public static function make($string, $salt = '') {
            return hash('sha512', $string . $salt);
        }
        public static function salt($length) {
            return mcrypt_create_iv($length);
        }
        public static function unique() {
            return self::make(uniqid());
        }
    }

所以,现在我将详细解释问题是什么。

当我注册时,我使用 Hash:: make() 函数在将密码和盐存储在数据库中之前对他们的密码进行哈希处理。当他们尝试登录时,在login.php中,我在User类中调用login函数来进行登录。当登录功能检查详细信息是否正确时,它会获取输入的密码和存储在输入用户名下的数据库中的盐,并对其进行哈希处理。然后它获取存储在数据库中的哈希值,并检查新哈希值是否与存储的哈希值相同。如果是,则密码正确,否则不正确。但是由于某种我无法弄清楚的原因,它总是告诉我我输入了无效的密码。

一切都在另一个项目中工作,但由于某种原因我无法让它在这个项目中工作,我确实将旧项目中的代码与这个项目进行了比较。

感谢所有帮助,如果有人需要任何信息才能提供帮助,请告诉我,我会添加它。

提前感谢,

布萨尔纳

让我给你一个替代的例子,使用 password_hash()password_verify() 正如我在上面的评论中所建议的那样。 我想你会看到这可以大大简化你的设计。

首先,让我们谈谈数据库模式。 对于此用例,您只需要一个与保存密码哈希相关的数据库列。在本练习中,假设它是 varchar(255),这是一个很好的推荐列大小。

若要基于输入密码创建哈希,代码如下所示:

// I assume you have sanitized the password at this point
// and stored in this $password variable.
// You should also enforce password length limit of 72 characters.
$password = ...; 
$password_hash = password_hash($password, PASSWORD_DEFAULT);    
if(false === $password_hash) {
   // something went wrong. log error
} else {
   // make your SQL insert to single password_hash field
   // note that the hash itself contains information on
   // the encryption methodology used and the salt
   // that was randomly generated to create the hash
}

为了验证密码,代码如下所示:

// I am assuming you have user input password
// you want to verify in variable $password_input
// and that you have already retrieved password hash
// from DB and have that stored in $password_hash
$password_input = ...;
$password_hash = ...;
$passwords_match = password_verify($password_input, $password_hash);
if (false === $passwords_match) {
    // password does not match. abort login        
} else {
    // password match. log user in
}

如您所见,哈希生成和哈希验证各需要一行代码。 没有比这更简单

的了。

从你所说的,如果相同的代码在另一个项目中工作。我建议您检查您的数据库。检查hash列长度,您应该将其设置为足够大以适合整个哈希(它们通常很长)。

当列长短于实际值时,数据库将存储哈希的截断版本,因此密码检查将始终失败。