我无法从表中获取另一行以获得登录访问权限


I cant get another row from table to get login access

我从www.phpacademy.org上发布的名为"注册和登录"的视频教程中复制了一个登录脚本

我的登录页面包含以下代码。。。


<?php
if (empty($_POST) === false ) {
    $username = $_POST['username'];
    $password = $_POST['password'];
    if (empty($username) === true || empty($password) === true) {
        $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: You need to enter <u>Username</u> and <u>Password</u>!</div>';
        }
    else if (user_exists($username) === false){
        $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: We are not able to get username <u>'.$username.'</u>. Please check your entered details.</div>';
        }
    else if (user_active($username) === false){
        $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: You need to activate your account by confirming your email address.<br> Check inbox and span folder for confirmation email.</div>';
        }
    else if (strlen($password) > 32 || (strlen($password) < 6 ) ) {
        $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: Your password must be between 6 and 32 characters.</div>';
    }       
    else {
        $login = login($username, $password);
            if ($login === false) {
            $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: Your Username or Password is incorrect. Please enter correct details.</div>';
            } else {
                $_SESSION['uid'] = $login;
                header ('Location: /home');
                exit ();
            }
        }
}

?>

然后登录表单

我的登录表单功能页面的代码是


<?php
function sanitize($data) {
    return mysql_real_escape_string($data);
}
function user_data($uid){
        $data = array();
        $uid = (int)$uid;
        $func_num_args = func_num_args();
        $func_get_args = func_get_args();
    if ($func_num_args > 0) {
        unset ($func_get_args[0]);
        $fields = '`' . implode ('`,`',$func_get_args) . '`';
        $data = mysql_fetch_assoc(mysql_query("SELECT $fields FROM `users` WHERE `uid` = $uid"));
        return $data;
    }   
}
function user_logged_in() {
    return (isset($_SESSION['uid'])) ? true : false ;
}
function user_exists($username){
    $username = sanitize($username);
    return (mysql_result(mysql_query("SELECT `uid` FROM `users` WHERE `uname` = '$username'"), 0) == 1) ? true : false;
}
function user_active($username){
    $username = sanitize($username);
    return (mysql_result(mysql_query("SELECT `uid` FROM `users` WHERE `uname` = '$username' AND `active` = 1"), 0) == 1) ? true : false;
}
function uid_from_uname($username){
    $username = sanitize($username);
    return mysql_result(mysql_query("SELECT `uid` FROM `users` WHERE `uname` = '$username' "), 0, 'uid');
}
function login($username, $password){
    $uid = uid_from_uname($username);
    $username = sanitize($username);    
    $password = md5($password);
    return (mysql_result(mysql_query("SELECT `uid` FROM `users` WHERE `uname` = '$username' AND `password` = '$password'"), 0) == 1) ? $uid : false ; 
}
?>

在那个视频中,他们在查询中使用了"SELECT COUNT(user_id)……",这在我的系统中不起作用。我正在使用示例1.7.7

问题是,在我的数据库表的第一行中,"id=1"、"username=virive.joshi"answers"pass=password"

它允许我输入而不显示任何错误,第二行的数据是"id=2"、"username=viral4ever"answers"pass=password",当我输入这个id pass时,它显示错误,即Cant find username viral4ever。

我编辑了第一行的用户名,并将其更改为viral4ever,这样我就可以访问了。所以请帮我访问每一行。我的数据库表的详细信息是"InnoDB"latin1_swidish_ci",列的详细信息username的排序规则是"utf8_bin",其他的是"utf4_unicode_ci"。两者都是varchar可接受的,uid是int。请任何人帮助我。

你也可以试试这个

$username = sanitize($username);
$sql = "SELECT uid FROM users WHERE uname = '$username'";
$result = mysql_query($sql) or die(mysql_error());
if (mysql_num_rows($result) > 0) {
   return true;
} else {
   return false;
}

我已经将您的代码改进到更新版本。当然,这个解决方案假定数据库表和列的名称是正确的。此外,您必须将"host"、"user"、"pwd"answers"name"替换为实际值。

以下三个文件必须位于同一目录中。我只是假设创建和管理HTML表单本身还有另一种代码的平静。最好也将该代码放入LoginForm中,这样逻辑和表示就可以清楚地分开。这不会是一个现成的解决方案,因为我不了解整个情况。

此解决方案要求用户中有一个名为"salt"(不带")的附加列,并且密码按以下方式保存。md5不再安全,任何以md5为特色的教程都应该立即被忽略。该哈希解决方案使用双盐密码和sha1哈希算法。

dbconfig.inc.php:

<?php
$host = 'host';
$dbUser = 'user';
$dbPwd = 'pwd';
$dbName = 'name';

LoginForm.class.php:

<?php
require_once(__DIR__.'/LoginDatabase.class.php');
/**
 * Manages the login form..
 * 
 * @author      Jim Martens
 * @copyright   2013 Jim Martens
 * @license     http://www.gnu.org/licenses/lgpl-3.0 GNU Lesser General Public License, version 3
 */
class LoginForm {
    /**
     * Contains the login database object.
     * @var 'LoginDatabase
     */
    private $loginDatabase = null;
    /**
     * Contains the read username.
     * @var string
     */
    private $username = '';
    /**
     * Contains the read password.
     * @var string
     */
    private $password = '';
    /**
     * Contains the error text.
     * @var string
     */
    private $errorText = '';
    /**
     * Initializes the login form.
     */
    public function __construct() {
        $this->loginDatabase = new 'LoginDatabase();
        $this->run();
    }
    /**
     * Reads the form parameters.
     */
    public function readFormParameters() {
        if (isset($_POST['username'])) $this->username = trim($_POST['username']);
        if (isset($_POST['password'])) $this->password = trim($_POST['password']);
    }
    /**
     * Validates the input.
     */
    public function validate() {
        if (empty($this->username) || empty($this->password)) {
            $this->errorText = 'You need to enter <u>Username</u> and <u>Password</u>!';
            throw new 'Exception($this->errorText);
        }
        if (!$this->loginDatabase->userExists($this->username)) {
            $this->errorText = 'A user with the username <u>'.$this->username.'</u> doesn''t exist. Please check your entered details.</div>';
            throw new 'Exception($this->errorText);
        }
        if (!$this->loginDatabase->userIsActive($this->username)) {
            $this->errorText = 'You need to activate your account by confirming your email address.<br> Check inbox and span folder for confirmation email.';
            throw new 'Exception($this->errorText);
        }
        if (strlen($this->password) > 32 || (strlen($this->password) < 6 ) ) {
            $this->errorText = 'Your password must be between 6 and 32 characters.';
            throw new 'Exception($this->errorText);
        }
        if (!$this->loginDatabase->isLoginValid($this->username, $this->password)) {
            $this->errorText = 'You have entered a wrong password.';
            throw new 'Exception($this->errorText);
        }
    }
    /**
     * Finishes the login process.
     */
    public function save() {
        $_SESSION['uid'] = $this->loginDatabase->getUserID($this->username);
    }
    /**
     * Runs the post form procedure.
     */
    private function run() {
        if (!empty($_POST)) {
            $this->readFormParameters();
            try {
                $this->validate();
                $this->save();
            }
            catch ('Exception $e) {
                $error = '<div id="error" style="font-size:16px; font-family: ''Armata'';">Error: '
                    . $this->errorText .'</div>';
                // where should error be displayed?
            }
        }
    }
}
new LoginForm();

这里是登录数据库.class.php:

<?php
/**
 * Manages the login procedure.
 * 
 * @author      Jim Martens
 * @copyright   2013 Jim Martens
 * @license     http://www.gnu.org/licenses/lgpl-3.0 GNU Lesser General Public License, version 3
 */
class LoginDatabase {
    /**
     * Contains the mysqli object.
     * @var 'mysqli
     */
    private $mysqli = null;
    /**
     * Contains the database table name.
     * @var string
     */
    private $table = 'users';
    /**
     * Contains the users.
     * @var array
     */
    private $users = array();
    /**
     * Contains the userIDs mapped to the respective names.
     * @var integer[]
     */
    private $userIDsToName = array();
    /**
     * Initializes the login database.
     */
    public function __construct() {
        include('dbconfig.inc.php');
        $this->mysqli = new 'mysqli($host, $dbUser, $dbPwd, $dbName);
        if ($this->mysqli->connect_error) {
            die('Connect Error (' . $this->mysqli->connect_errno . ') '
                . $this->mysqli->connect_error);
        }
        $this->cacheQuery();
    }
    /**
     * Closes the connection.
     */
    public function __destruct() {
        $this->mysqli->close();
    }
    /**
     * Returns the userID for an existing user.
     * 
     * @param   string  $username
     * @return  integer
     * 
     * @require userExists($username)
     */
    public function getUserID($username) {
        $username = trim($username);
        return $this->userIDsToName[$username];
    }
    /**
     * Checks if a user exists.
     * 
     * @param   string  $username
     * @return  boolean
     */
    public function userExists($username) {
        $username = trim($username);
        $userExists = false;
        foreach ($this->users as $userID => $user) {
            if ($user['username'] == $username) {
                $userExists = true;
                break;
            }
        }
        return $userExists;
    }
    /**
     * Checks if a user is active.
     * 
     * @param   string  $username
     * @return  boolean
     */
    public function userIsActive($username) {
        $username = trim($username);
        $isActive = $this->userExists($username);
        if ($isActive) {
            $userID = $this->userIDsToName[$username];
            $user = $this->users[$userID];
            $isActive = $user['isActive'];
        }
        return $isActive;
    }
    /**
     * Checks if the login is valid.
     * 
     * @param   string  $username
     * @param   string  $password
     * @return  boolean
     */
    public function isLoginValid($username, $password) {
        $username = trim($username);
        $password = trim($password);
        $loginValid = $this->userIsActive($username);
        if ($loginValid) {
            $userID = $this->userIDsToName[$username];
            $user = $this->users[$userID];
            $salt = $user['salt'];
            $hashedPassword = sha1($password . sha1($password.$salt));
            $loginValid = ($hashedPassword == $user['password']);
        }
        return $loginValid;
    }
    /**
     * Reads all users from database.
     */
    private function cacheQuery() {
        $sql = 'SELECT uid, uname, password, salt, active
                FROM   '.$this->table;
        if ($result = $this->mysqli->query($sql, MYSQLI_USE_RESULT)) {
            /* @var $result mysqli_result */
            while ($row = $result->fetch_assoc() !== NULL) {
                $row = array(
                    'userID' => intval($row['uid']),
                    'username' => $row['uname'],
                    'password' => $row['password'],
                    'salt' => $row['salt'],
                    'isActive' => (boolean) $row['active']
                );
                $this->users[$row['userID']] = $row;
                $this->userIDsToName[$row['username']] = $row['userID'];
            }
            $result->free();
        }
    }
}

这完全是消耗性代码。所有的数据库操作都只是假设什么都不会失败。这是一个非常非常糟糕的设计。数据库和查询可能总是失败。同样,您的代码似乎从未真正连接到数据库,除非您只是没有显示任何代码。

一个更好、更容易调试的功能版本是:

$username = sanitize($username);
$sql = "SELECT uid FROM users WHERE uname = '$username'";
$result = mysql_query($sql) or die(mysql_error());
if (mysql_num_rows($result) == 0) {
   return false;
} else {
   return true;
}

这将正确地处理数据库错误,如果需要的话,为您提供用于调试的实际查询,并且properly会查找结果,而不会假设会有结果。

当然,从更大的角度来看,您不应该使用mysql_()函数编写新代码。它们已被废弃和弃用。如果你刚开始,那么假设mysql_()已经不存在了,然后开始使用mysqli(注意i)或PDO。