我从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"one_answers"pass=password"
它允许我输入而不显示任何错误,第二行的数据是"id=2"、"username=viral4ever"one_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"one_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。