使用 php 在 mysql 中存储会话数据无法从表中正确检索数据
我在使用 php 和 mysql 从 $_SESSION 检索一些数据时遇到问题。我已经注释掉了 php.ini 中告诉服务器使用“文件”来存储会话信息的行,以便使用我的数据库。我有一个类,我用它来将信息写入数据库并且它工作正常。当用户传递其凭据时,该类将被实例化并设置 $_SESSION 变量,然后用户将被重定向到索引页面。 index.php 页面包含数据库会话类所在的文件,该文件在实例化时调用 session_start() 并且会话变量应该位于 $_SESSION 中,但是当我执行 var_dump($_SESSION) 时,数组中没有任何内容。但是,当我查看mysql中的数据时,所有会话信息都在那里。它的行为就像 session_start() 没有被调用,但是通过实例化它的类。
知道可能出什么问题吗?
这是 HTML:
<?php
include_once "classes/phpsessions_db/class.dbsession.php"; //used for sessions
var_dump($_SESSION);
?>
<html>
.
.
.
</html>
这是 dbsession 类:
<?php
error_reporting(E_ALL);
class dbSession
{
function dbSession($gc_maxlifetime = "", $gc_probability = "", $gc_divisor = "")
{
// if $gc_maxlifetime is specified and is an integer number
if ($gc_maxlifetime != "" && is_integer($gc_maxlifetime)) {
// set the new value
@ini_set('session.gc_maxlifetime', $gc_maxlifetime);
}
// if $gc_probability is specified and is an integer number
if ($gc_probability != "" && is_integer($gc_probability)) {
// set the new value
@ini_set('session.gc_probability', $gc_probability);
}
// if $gc_divisor is specified and is an integer number
if ($gc_divisor != "" && is_integer($gc_divisor)) {
// set the new value
@ini_set('session.gc_divisor', $gc_divisor);
}
// get session lifetime
$this->sessionLifetime = ini_get("session.gc_maxlifetime");
//Added by AARON. cancel the session's auto start,important, without this the session var's don't show up on next pg.
session_write_close();
// register the new handler
session_set_save_handler(
array(&$this, 'open'),
array(&$this, 'close'),
array(&$this, 'read'),
array(&$this, 'write'),
array(&$this, 'destroy'),
array(&$this, 'gc')
);
register_shutdown_function('session_write_close');
// start the session
@session_start();
}
function stop()
{
$new_sess_id = $this->regenerate_id(true);
session_unset();
session_destroy();
return $new_sess_id;
}
function regenerate_id($return_val=false)
{
// saves the old session's id
$oldSessionID = session_id();
// regenerates the id
// this function will create a new session, with a new id and containing the data from the old session
// but will not delete the old session
session_regenerate_id();
// because the session_regenerate_id() function does not delete the old session,
// we have to delete it manually
//$this->destroy($oldSessionID);
//ADDED by aaron
// returns the new session id
if($return_val)
{
return session_id();
}
}
function open($save_path, $session_name)
{
// global $gf;
// $gf->debug_this($gf, "GF: Opening Session");
// change the next values to match the setting of your mySQL database
$mySQLHost = "localhost";
$mySQLUsername = "user";
$mySQLPassword = "pass";
$mySQLDatabase = "sessions";
$link = mysql_connect($mySQLHost, $mySQLUsername, $mySQLPassword);
if (!$link) {
die ("Could not connect to database!");
}
$dbc = mysql_select_db($mySQLDatabase, $link);
if (!$dbc) {
die ("Could not select database!");
}
return true;
}
function close()
{
mysql_close();
return true;
}
function read($session_id)
{
$result = @mysql_query("
SELECT
session_data
FROM
session_data
WHERE
session_id = '".$session_id."' AND
http_user_agent = '".$_SERVER["HTTP_USER_AGENT"]."' AND
session_expire > '".time()."'
");
// if anything was found
if (is_resource($result) && @mysql_num_rows($result) > 0) {
// return found data
$fields = @mysql_fetch_assoc($result);
// don't bother with the unserialization - PHP handles this automatically
return unserialize($fields["session_data"]);
}
// if there was an error return an empty string - this HAS to be an empty string
return "";
}
function write($session_id, $session_data)
{
// global $gf;
// first checks if there is a session with this id
$result = @mysql_query("
SELECT
*
FROM
session_data
WHERE
session_id = '".$session_id."'
");
// if there is
if (@mysql_num_rows($result) > 0)
{
// update the existing session's data
// and set new expiry time
$result = @mysql_query("
UPDATE
session_data
SET
session_data = '".serialize($session_data)."',
session_expire = '".(time() + $this->sessionLifetime)."'
WHERE
session_id = '".$session_id."'
");
// if anything happened
if (@mysql_affected_rows())
{
// return true
return true;
}
}
else // if this session id is not in the database
{
// $gf->debug_this($gf, "inside dbSession, trying to write to db because session id was NOT in db");
$sql = "
INSERT INTO
session_data
(
session_id,
http_user_agent,
session_data,
session_expire
)
VALUES
(
'".serialize($session_id)."',
'".$_SERVER["HTTP_USER_AGENT"]."',
'".$session_data."',
'".(time() + $this->sessionLifetime)."'
)
";
// insert a new record
$result = @mysql_query($sql);
// if anything happened
if (@mysql_affected_rows())
{
// return an empty string
return "";
}
}
// if something went wrong, return false
return false;
}
function destroy($session_id)
{
// deletes the current session id from the database
$result = @mysql_query("
DELETE FROM
session_data
WHERE
session_id = '".$session_id."'
");
// if anything happened
if (@mysql_affected_rows()) {
// return true
return true;
}
// if something went wrong, return false
return false;
}
function gc($maxlifetime)
{
// it deletes expired sessions from database
$result = @mysql_query("
DELETE FROM
session_data
WHERE
session_expire < '".(time() - $maxlifetime)."'
");
}
} //End of Class
$session = new dbsession();
?>
I have a problem retrieving some data from the $_SESSION using php and mysql. I've commented out the line in php.ini that tells the server to use the "file" to store the session info so my database will be used. I have a class that I use to write the information to the database and its working fine. When the user passes their credentials the class gets instantiated and the $_SESSION vars get set, then the user gets redirected to the index page. The index.php page includes the file where the db session class is, which when instantiated calles session_start() and the session variables should be in $_SESSION, but when I do var_dump($_SESSION) there is nothing in the array. However, when I look at the data in mysql, all the session information is in there. Its acting like session_start() has not been called, but by instantiating the class it is.
Any idea what could be wrong?
Here's the HTML:
<?php
include_once "classes/phpsessions_db/class.dbsession.php"; //used for sessions
var_dump($_SESSION);
?>
<html>
.
.
.
</html>
Here's the dbsession class:
<?php
error_reporting(E_ALL);
class dbSession
{
function dbSession($gc_maxlifetime = "", $gc_probability = "", $gc_divisor = "")
{
// if $gc_maxlifetime is specified and is an integer number
if ($gc_maxlifetime != "" && is_integer($gc_maxlifetime)) {
// set the new value
@ini_set('session.gc_maxlifetime', $gc_maxlifetime);
}
// if $gc_probability is specified and is an integer number
if ($gc_probability != "" && is_integer($gc_probability)) {
// set the new value
@ini_set('session.gc_probability', $gc_probability);
}
// if $gc_divisor is specified and is an integer number
if ($gc_divisor != "" && is_integer($gc_divisor)) {
// set the new value
@ini_set('session.gc_divisor', $gc_divisor);
}
// get session lifetime
$this->sessionLifetime = ini_get("session.gc_maxlifetime");
//Added by AARON. cancel the session's auto start,important, without this the session var's don't show up on next pg.
session_write_close();
// register the new handler
session_set_save_handler(
array(&$this, 'open'),
array(&$this, 'close'),
array(&$this, 'read'),
array(&$this, 'write'),
array(&$this, 'destroy'),
array(&$this, 'gc')
);
register_shutdown_function('session_write_close');
// start the session
@session_start();
}
function stop()
{
$new_sess_id = $this->regenerate_id(true);
session_unset();
session_destroy();
return $new_sess_id;
}
function regenerate_id($return_val=false)
{
// saves the old session's id
$oldSessionID = session_id();
// regenerates the id
// this function will create a new session, with a new id and containing the data from the old session
// but will not delete the old session
session_regenerate_id();
// because the session_regenerate_id() function does not delete the old session,
// we have to delete it manually
//$this->destroy($oldSessionID);
//ADDED by aaron
// returns the new session id
if($return_val)
{
return session_id();
}
}
function open($save_path, $session_name)
{
// global $gf;
// $gf->debug_this($gf, "GF: Opening Session");
// change the next values to match the setting of your mySQL database
$mySQLHost = "localhost";
$mySQLUsername = "user";
$mySQLPassword = "pass";
$mySQLDatabase = "sessions";
$link = mysql_connect($mySQLHost, $mySQLUsername, $mySQLPassword);
if (!$link) {
die ("Could not connect to database!");
}
$dbc = mysql_select_db($mySQLDatabase, $link);
if (!$dbc) {
die ("Could not select database!");
}
return true;
}
function close()
{
mysql_close();
return true;
}
function read($session_id)
{
$result = @mysql_query("
SELECT
session_data
FROM
session_data
WHERE
session_id = '".$session_id."' AND
http_user_agent = '".$_SERVER["HTTP_USER_AGENT"]."' AND
session_expire > '".time()."'
");
// if anything was found
if (is_resource($result) && @mysql_num_rows($result) > 0) {
// return found data
$fields = @mysql_fetch_assoc($result);
// don't bother with the unserialization - PHP handles this automatically
return unserialize($fields["session_data"]);
}
// if there was an error return an empty string - this HAS to be an empty string
return "";
}
function write($session_id, $session_data)
{
// global $gf;
// first checks if there is a session with this id
$result = @mysql_query("
SELECT
*
FROM
session_data
WHERE
session_id = '".$session_id."'
");
// if there is
if (@mysql_num_rows($result) > 0)
{
// update the existing session's data
// and set new expiry time
$result = @mysql_query("
UPDATE
session_data
SET
session_data = '".serialize($session_data)."',
session_expire = '".(time() + $this->sessionLifetime)."'
WHERE
session_id = '".$session_id."'
");
// if anything happened
if (@mysql_affected_rows())
{
// return true
return true;
}
}
else // if this session id is not in the database
{
// $gf->debug_this($gf, "inside dbSession, trying to write to db because session id was NOT in db");
$sql = "
INSERT INTO
session_data
(
session_id,
http_user_agent,
session_data,
session_expire
)
VALUES
(
'".serialize($session_id)."',
'".$_SERVER["HTTP_USER_AGENT"]."',
'".$session_data."',
'".(time() + $this->sessionLifetime)."'
)
";
// insert a new record
$result = @mysql_query($sql);
// if anything happened
if (@mysql_affected_rows())
{
// return an empty string
return "";
}
}
// if something went wrong, return false
return false;
}
function destroy($session_id)
{
// deletes the current session id from the database
$result = @mysql_query("
DELETE FROM
session_data
WHERE
session_id = '".$session_id."'
");
// if anything happened
if (@mysql_affected_rows()) {
// return true
return true;
}
// if something went wrong, return false
return false;
}
function gc($maxlifetime)
{
// it deletes expired sessions from database
$result = @mysql_query("
DELETE FROM
session_data
WHERE
session_expire < '".(time() - $maxlifetime)."'
");
}
} //End of Class
$session = new dbsession();
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我怀疑如果您的错误报告工作正常,其不工作的原因就会很清楚。
您不会转义会话数据,也不应该序列化 ID。巧合的是,您的代码很混乱,文档记录不完整且效率低下 - 例如,您不需要查看是否已经有数据然后选择进行插入或更新:
并且....
(!)就像您的评论所说的那样 - 不要尝试在处理程序中反序列化数据。
C.
I suspect the reason its not working would be clear if your error reporting was working correctly.
You're not escaping the session data, and should NOT be serializing the ID. Coincidentally, your code is messy, badly documented and inefficient - e.g. you don't need to see if you already have data then choose to do an insert or update:
and....
(!) Like your comment says - don't try to unserialize the data in the handler.
C.
您在插入时序列化 session_id,但没有在其他地方序列化。尝试改变这一点...
You're serializing the session_id on insert, but nowhere else. Try changing that...