登录功能仅适用一次

时间:2014-10-04 14:14:10

标签: php mysqli

我有以下用于处理用户登录的php函数。这些函数是User类的一部分。

/*
 * detail() function to get a detail from a database
 * exists() function to check if something exists in a database
 */

private function generate($password, $username = null) {
    if(is_null($username)) {
        $date = '0000-00-00';
    } else {
        $date = $this->_db->detail('last_active', 'users', 'username', $username);
    }

    // This is not the real thing but it will do as an example
    $salt = md5(strrev($password.$date));
    $password = md5($salt.$password.$date).strrev($password);

    return $password;
}

public function login($data = array()) {
    // Check if the user exists
    $username = $data['username'];
    if($this->_db->exists('username', 'users', 'username', $username)) {
        $password = $this->generate($data['password'], $username);

        // If the account is active
        if ($this->_db->detail('active', 'users', 'username', $username) === 1) {
            $stmt = $this->_db->mysqli->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ? AND `active` = 1");
            $stmt->bind_param('ss', $username, $password);
            $stmt->execute();
            $stmt->store_result();

            if($stmt->num_rows >= 1) {
                // Function to update last_active
                if($this->updateLastActive($username)) {
                    // Function to update password
                    if($this->updatePassword($username, $this->generate($password, $username))) {
                        // Set the session
                        $this->_session->set('user', $this->_db->detail('id', 'users', 'username', $username));

                        if($this->_session->exists('user')) {
                            return true;
                        } else {
                            echo 'Logging in went wrong';
                            return false;
                        }
                    } else {
                        echo 'Editing the password went wrong';
                        return false;
                    }
                } else {
                    echo 'Editing last active date went wrong';
                    return false;
                }
            } else {
                echo 'Wrong username and password combination';
                return false;
            }
        } else {
            echo 'Account not active';
            return false;
        }
    } else {
        echo 'Username doesn\'t exists';
        return false;
    }
}

private function updateLastActive($username) {
    $date = date('Y-m-d');

    $stmt = $this->_db->mysqli->prepare("UPDATE `users` SET `last_active` = ? WHERE `username` = ?");
    $stmt->bind_param('ss', $date, $username);
    $stmt->execute();

    if($stmt->affected_rows >= 1) {
        return true;
    } else {
        return false;
    }
}

private function updatePassword($username, $password) {
    $stmt = $this->_db->mysqli->prepare("UPDATE `users` SET `password` = ? WHERE `username` = ?");
    $stmt->bind_param('ss', $password, $username);
    $stmt->execute();

    if($stmt->affected_rows >= 1) {
        return true;
    } else {
        return false;
    }
}

用户刚刚注册时可以毫无问题地登录。但是当用户注销并尝试再次登录时,它将失败。我收到错误的部分如下:

$stmt = $this->_db->mysqli->prepare("SELECT `username`, `password` FROM `users` WHERE `username` = ? AND `password` = ? AND `active` = 1");

我尝试在函数的不同位置找出脚本在echo处失败的位置,但我无法找到错误。 generate()函数具有$username = null的原因是因为相同的函数用于注册。

所以所有函数都在工作,但它们只能工作一次所以这让我觉得generate()函数中的某些函数是错误的。我总是得到用户名/密码组合有问题的消息

如果有人能指出我正确的方向,我会非常高兴。

提前致谢

更新 detail()exists()函数是类Database的一部分。

public function detail($detail, $table, $column, $value) {
        if(is_array($detail)) {
            $data = array();

            foreach($detail as $key) {
                $stmt = $this->mysqli->prepare("SELECT `$key` FROM `$table` WHERE `$column` = ?");
                if(is_numeric($value)) {
                    $stmt->bind_param('i', $value);
                } else {
                    $stmt->bind_param('s', $value);
                }
                $stmt->execute();
                $stmt->bind_result($detail);
                $stmt->fetch();
                $data[] = $detail;
                $stmt = null;
            }

            return $data;
        } else {
            $stmt = $this->mysqli->prepare("SELECT `$detail` FROM `$table` WHERE `$column` = ?");

            if(is_numeric($value)) {
               $stmt->bind_param('i', $value);
            } else {
                $stmt->bind_param('s', $value);
            }
            $stmt->execute();
            $stmt->bind_result($detail);
            $stmt->fetch();

            return $detail;
        }
    }

    public function exists($detail, $table, $column, $value) {
        $stmt = $this->mysqli->prepare("SELECT `$detail` FROM `$table` WHERE `$column` = ?");
        switch(is_numeric($value)) {
            case true:
                $stmt->bind_param('i', $value);
                break;
            case false:
                $stmt->bind_param('s', $value);
                break;
        }
        $stmt->execute();
        $stmt->store_result();

        if($stmt->num_rows >= 1) {
            return true;
        } else {
            return false;
        }
    }

1 个答案:

答案 0 :(得分:1)

在表格中创建一个哈希字段,使其足够长以避免长度问题。

md5()现在不被接受,您应该使用更好的哈希函数,例如password_hash()

<强>注册

private function register($username, $password) {
    //safer than md5() anyway
    $hash = password_hash($password, PASSWORD_DEFAULT);
    $sql = 'INSERT INTO table_name (`username`, `hash`) VALUES (?, ?);'
    $stmt = $this->_db->mysqli->prepare($sql);
    $stmt->bind_param('ss', $username, $hash);
    $stmt->execute();

    if($stmt->affected_rows >= 1) {
        return true;
    } else {
        return false;
    }
}

登录:

public function login($username, $password) {
    // Check if the user exists
    if($this->_db->exists('username', 'users', 'username', $username)) {
        // If the account is active
        if ($this->_db->detail('active', 'users', 'username', $username) === 1) {
            $sql = 'SELECT `username`, `hash` FROM `users` WHERE `username` = ? AND `active` = 1';
            $stmt = $this->_db->mysqli->prepare();
            $stmt->bind_param('ss', $username, $hash);
            $stmt->execute();
            $stmt->store_result();

            if($stmt->num_rows === 1) {
                if (password_verify($password, $hash)) {
                    // Function to update last_active
                    if($this->updateLastActive($username)) {
                        echo 'last active updated, Login successful';
                        return true;
                    } else {
                        echo 'Editing last active date went wrong';
                        return false;
                    }
                } else {
                    echo 'Wrong username and password combination';
                    return false;
                }
            } else {
                echo 'Account not active';
                return false;
            }
        } else {
            echo 'Username doesn\'t exists';
            return false;
        }
    }
}

当然你仍然可以使用自定义盐,例如

$hash = password_hash($password
                     ,PASSWORD_DEFAULT
                     ,array('salt' =>generate()));//generate() returns the salt