在实习期间,我将继续学习一个非常好的教程,该教程为购物车进行高级PHP安全会话,这将为用户提供个人级别的定价(无论如何,这就是目标。)
这是本教程:
http://tutorial-resource.com/2011/10/a-secure-session-management-class-in-php/
首先,我创建了一个原始登录名,用于基于Quickbooks客户ID检查现有客户,以测试此会话。真正的处理使用注册,登录名和密码。然后,我做了一个登录检查器,该数据库在mysql数据库中找到用户,并在找到该用户时,逐页检索需要与用户在一起的用户数据列。 (我保证在完成这项工作后,我将进一步防止SQL注入。)我添加了一些其他字段存储在SessionData中。
<?php
include "class.session.php";
if(empty($_POST['customer_id']))
{
$this->HandleError("Customer ID is empty!");
return false;
}
$customer_id = trim($_POST['customer_id']);
$dbuser = "CENSORED";
$dbpass = "CENSORED";
$host = "localhost";
$dbname = "CENSORED";
// database connection
mysql_connect("localhost", $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die("Unable to select database");
//This query grabs all the puchases going back up to three months
//This debug line displays the query
$query = "SELECT * FROM customers";
echo $query."<br>";
$found = 0;
$result = mysql_query($query);
while($row=mysql_fetch_array($result))
{
//Grab the database pieces the customer will need throughout the page.
echo "Checking customer number ".$row['customer_id']."<br>";
if ($row['customer_id'] == $customer_id)
{
$found = 1;
break;
}
}
//-create while loop and loop through result set
if ($found == 0)
{
echo 'Wrong customer number';
}
while($row=mysql_fetch_array($result))
{
//Grab the database pieces the customer will need throughout the page.
$customer_id = $row['customer_id'];
$first_name = $row['first_name'];
$last_name = $row['last_name'];
$first_name = $row['price_level'];
}
//Give the user a session.
$sessions = new sessionsClass;
$sessions->_sessionStart();
$sessionInfo = $sessions->sessionCheck();
if( $sessionInfo = false )
{
# This session is invalid. Tell the user.
}
else
{
# Update the name.
$sessionInfo->sessionData['customer_id'] = $customer_id;
$sessionInfo->sessionData['company_name'] = $company_name;
$sessionInfo->sessionData['first_name'] = $first_name;
$sessionInfo->sessionData['last_name'] = $last_name;
$sessionInfo->sessionData['price_level'] = $price_level;
$sessionInfo->setSessionData();
# Session is valid, can use the data.
echo "Your name is ".$sessionInfo->sessionData['first_name']." ".$sessionInfo->sessionData['last_name']."<br>";
}
?>
成功登录后,我在error_log中看到一条错误消息,内容为
当明显存在该函数时,直接在本教程中就此行“调用未定义方法stdClass :: setSessionData()”:
$ sessionInfo-> setSessionData();
为什么登录名不能将setSessionData识别为未定义的方法而不是函数?
我不完全了解的一个线索是,它将setSessionData称为“未定义的方法stdClass”,而不是“未定义的函数”。该功能与本教程非常相似,区别在于它连接到我的数据库:
public function setSessionData()
{
$dbuser = "CENSORED";
$dbpass = "CENSORED";
$host = "localhost";
$dbname = "CENSORED";
// database connection
mysql_connect("localhost", $dbuser, $dbpass) or die(mysql_error());
mysql_select_db($dbname) or die("Unable to select database");
//Encrypt the data.
$serialiseData = serialize( $this->sessionData );
//Update the session data.
mysql_query( "UPDATE sessions SET sessionData = '{$serialiseData}' WHERE sessionHash = '{$this->sessionHash}'" );
}
我的最后一个问题是,无论哪个页面,每个单独的页面都需要什么才能安全地区分普通用户和登录用户?是这样吗
if (sessionCheck == false)
{show ordinary stuff}
else if (sessionCheck == return true)
{show personalized stuff}
编辑本教程毕竟似乎有一些问题。例如,在本教程快结束时。
# Session is valid, can use the data.
echo "Your name is " . $sessionInfo->sessionData['fullname'];
# Update the name.
$sessionInfo->sessionData['fullname'] = "My New name";
$sessionInfo->setSessionData();
}
这是错误的,因为sessionInfo是一个布尔值,表示为false时返回true。相反,我用
$sessions->sessionData['customer_id'] = $customer_id;
$sessions->sessionData['company_name'] = $company_name;
$sessions->sessionData['first_name'] = $first_name;
$sessions->sessionData['last_name'] = $last_name;
$sessions->sessionData['price_level'] = $price_level;
$sessions->setSessionData();
但这仍然不能解决问题。同样,本教程让人们创建了一个完整的MySQL数据库,但在班级或本教程中的任何地方都没有发生一次INSERT。提供了对现有会话的UPDATE查询功能,但是没有用于创建新会话的功能。我可以添加什么来使数据库成功创建会话?
最佳答案
如果在反序列化期间找不到该类,则已序列化的对象将转换为stdClass
。我的猜测是,当您从数据库中读取会话信息并将其放回sessionClass
对象时,您尚未包含定义该类的文件。在反序列化之前,请确保已定义该类。
由于stdClass
没有名为setSessionData
的方法,因此会出现“调用未定义方法”错误。方法是通常用于在类中引用函数的术语,而函数只是独立的函数定义。
为了在每个页面上将登录用户与普通用户区分开,通常需要启动会话并检查特定于应用程序的值,该值向您表明该用户已通过身份验证。这可能很简单,例如在会话中设置loggedIn
标志,或者存储更复杂的类型并检查其值。但是基本上,您需要在从登录用户那里认识普通用户所需的每个页面上执行此操作。
希望能有所帮助。
顺便说一句,在代码开始处调用$this->HandleError("Customer ID is empty!");
的地方,如果执行该块,则会收到一条错误消息,提示未定义$this
。由于未在类中调用该代码,因此没有$this
实例,因此您必须找出正确的方法来处理该错误。