【发布时间】:2013-12-01 05:59:55
【问题描述】:
我知道这个问题已经被问过很多次了,我已经搜索过了,尝试了提供的每一种组合和我能想到的每一种方法,但我仍然不知所措..
这是场景:
我刚刚编写并全面测试了登录系统。代码按其应有的方式处理,但 $_SESSION 并未延续。
假设我输入了正确的详细信息:
我检查了多个不同的东西。 print_r($_SESSION) 在提交表单时在索引(登录所在的位置)上返回“Array( [user] => 1 )”,但在下一页(dashboard.php)上返回“Array( )”
这是我的 index.php
<?php
include(__DIR__ . '/includes/class_mtg_sessions.php');
$session = new Session();
$session->start_session('_mtg', true);
if(isset($_SESSION['user'])) {
header("Location: dashboard.php");
exit;
}
include(__DIR__ . '/includes/header.php');
?><div id="templatemo_main">
<div class="content_wrapper">
<div class="col_1">
<h2>Client Area</h2>
<p><img src="<?php echo IMAGE_URL; ?>/icon_04.png" alt="Image 4" class="img_fl" /></p>
<p><div id="contact_form" class="col_2 left">
<h3>Login</h3><?php
if(isset($_POST['submit'])) {
$str = array('name', 'password');
foreach($str as $what) {
$_POST[$what] = isset($_POST[$what]) && is_string($_POST[$what]) ? strtolower($db->escape(trim($_POST[$what]))) : null;
if(empty($_POST[$what]))
$mtg->error("You didn't enter a valid ".$what);
}
$selectUser = $db->query("SELECT `id` FROM `users` WHERE ((LOWER(`username`) = '".$_POST['name']."') OR (LOWER(`email`) = '".$_POST['name']."'))");
if(!$db->num_rows($selectUser))
$mtg->error("There doesn't appear to be anyone on record with that ".(filter_var($_POST['name'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username'));
$select = $db->query("SELECT `id`, `username` FROM `users` WHERE LOWER(`username`) = '".$_POST['name']."' OR LOWER(`email`) = '".$_POST['name']."' AND `password` = '".$mtg->fuzzehCrypt($_POST['password'])."'");
if(!$db->num_rows($select))
$mtg->error("Invalid ".(filter_var($_POST['name'], FILTER_VALIDATE_EMAIL) ? 'email' : 'username')."/password combination");
$row = $db->fetch_row($select);
$_SESSION['user'] = $row['id'];
$mtg->success("Welcome back ".$mtg->format($row['username'])."!<br />Redirecting you now...<meta http-equiv='refresh' content='3; url=dashboard.php' />");
echo "</div></div></div></div>";
include(__DIR__ . '/includes/footer.php');
exit;
}
?><form method="post" name="contact" action="index.php">
<div class="col_3">
<label for="name">ID</label>
<input name="name" type="text" class="required input_field" id="name" placeholder="Username/Email" required />
</div>
<div class="col_3 no_margin_right">
<label for="password">Password</label>
<input name="password" type="password" class="required input_field" id="password" maxlength="30" placeholder="Password" required />
</div>
<div class="clear"></div>
<input type="submit" name="submit" value="Submit" class="submit_btn left" />
<input type="reset" name="reset" value="Reset" class="submit_btn right" />
</form>
</div></p>
</div>
</div>
<div class="content_wrapper">
<div class="col_1">
<h2>New member?</h2>
<p><div id="contact_form" class="col_2 left">
Don't have an account? <a href='register.php'>Sign up now!</a><br />
It's completely free and it allows you to track everything about your order(s), place new orders, directly manage how your current order is being processed and much more!
</div></p>
</div>
</div>
</div><?php
include(__DIR__ . '/includes/footer.php');
这是dashboard.php
<?php
include(__DIR__ . '/includes/class_mtg_sessions.php');
$session = new Session();
$session->start_session('_mtg', true);
if(!isset($_SESSION['user'])) {
header("Location: index.php");
exit;
}
include(__DIR__ . '/includes/header.php');
$mtg->userdata($_SESSION['user']);
?> <div id="templatemo_main">
<div class="content_wrapper">
<div class="col_1">
<h2>Client Area</h2>
<p><img src="<?php echo IMAGE_URL; ?>/icon_04.png" alt="Image 4" class="img_fl" /></p>
<p><div id="contact_form" class="col_2 left">
<h3>Dashboard</h3>
Dashboard coming soon
</div></p>
</div>
</div>
</div><?php
include(__DIR__ . '/includes/footer.php');
最后,我正在使用的会话类。
<?php
ini_set('display_errors', true);
error_reporting(E_ALL);
class Session {
function __construct() {
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');
}
function start_session($session_name, $secure) {
if(in_array('sha512', hash_algos()))
ini_set('session.hash_function', 'sha512');
ini_set('session.hash_bits_per_character', 5);
ini_set('session.use_only_cookies', 1);
$cookieParams = session_get_cookie_params();
session_set_cookie_params($cookieParams['lifetime'], $cookieParams['path'], $cookieParams['domain'], $secure, true);
session_name($session_name);
session_start();
session_regenerate_id(true);
}
function open() {
include(__DIR__ . '/definitions.php');
$this->db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_BASE) or exit("Couldn't connect to the database");
return true;
}
function close() {
$this->db->close();
return true;
}
function read($id) {
if(!isset($this->read_stmt))
$this->read_stmt = $this->db->prepare("SELECT `data` FROM `sessions` WHERE `id` = ? LIMIT 1");
$this->read_stmt->bind_param('s', $id);
$this->read_stmt->execute();
$this->read_stmt->store_result();
$this->read_stmt->bind_result($data);
$this->read_stmt->fetch();
$key = $this->getkey($id);
$data = $this->decrypt($data, $key);
return $data;
}
function write($id, $data) {
$key = $this->getkey($id);
$data = $this->encrypt($data, $key);
$time = time();
if(!isset($this->w_stmt))
$this->w_stmt = $this->db->prepare("REPLACE INTO `sessions` (`id`, `set_time`, `data`, `session_key`) VALUES (?, ?, ?, ?)") or trigger_error(mysqli_error($this->db));
$this->w_stmt->bind_param('siss', $id, $time, $data, $key);
$this->w_stmt->execute();
return true;
}
function destroy($id) {
if(!isset($this->delete_stmt))
$this->delete_stmt = $this->db->prepare("DELETE FROM `sessions` WHERE `id` = ?") or trigger_error(mysqli_error($this->db));
$this->delete_stmt->bind_param('s', $id);
$this->delete_stmt->execute();
return true;
}
function gc($max) {
if(!isset($this->gc_stmt))
$this->gc_stmt = $this->db->prepare("DELETE FROM `sessions` WHERE `set_time` < ?") or trigger_error(mysqli_error($this->db));
@$this->gc_stmt->bind_param('s', (time() - $max));
$this->gc_stmt->execute();
return true;
}
private function getkey($id) {
if(!isset($this->key_stmt))
$this->key_stmt = $this->db->prepare("SELECT `session_key` FROM `sessions` WHERE `id` = ? LIMIT 1") or trigger_error(mysqli_error($this->db));
$this->key_stmt->bind_param('s', $id);
$this->key_stmt->execute();
$this->key_stmt->store_result();
if($this->key_stmt->num_rows == 1) {
$this->key_stmt->bind_result($key);
$this->key_stmt->fetch();
return $key;
} else {
$random_key = hash('sha512', uniqid(mt_rand(1, mt_getrandmax()), true));
return $random_key;
}
}
private function encrypt($data, $key) {
$salt = 'agar16565!sfrb0a0$£%^&njswdUEB(*£8034672839ngrwu*(£89bgaq90hmw4n';
$key = substr(hash('sha256', $salt . $key . $salt), 0, 32);
if(!function_exists('mcrypt_get_iv_size'))
exit("mCrypt not enabled");
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encrypted = base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $data, MCRYPT_MODE_ECB, $iv));
return $encrypted;
}
private function decrypt($data, $key) {
$salt = 'agar16565!sfrb0a0$£%^&njswdUEB(*£8034672839ngrwu*(£89bgaq90hmw4n';
$key = substr(hash('sha256', $salt . $key . $salt), 0, 32);
if(!function_exists('mcrypt_get_iv_size'))
exit("mCrypt not enabled");
$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($data), MCRYPT_MODE_ECB, $iv);
return $decrypted;
}
}
users 和sessions 表的数据库结构(使用SHOW CREATE TABLE):
CREATE TABLE `sessions` (
`id` char(128) NOT NULL,
`set_time` char(10) NOT NULL,
`data` text NOT NULL,
`session_key` char(128) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
KEY `session_key` (`session_key`),
KEY `set_time` (`set_time`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL DEFAULT '',
`email` varchar(255) NOT NULL DEFAULT '',
`verified` enum('Yes','No','Flagged') NOT NULL DEFAULT 'No',
`ver_code` varchar(255) NOT NULL DEFAULT '',
`password` varchar(255) NOT NULL DEFAULT '',
`ip` varchar(255) NOT NULL DEFAULT '',
`country` varchar(255) NOT NULL DEFAULT '',
`type` enum('standard','admin') NOT NULL DEFAULT 'standard',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
UNIQUE KEY `email` (`email`),
KEY `type` (`type`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
现在,我在同一服务器上托管的不同站点上使用相同的类,它工作得非常好。 我检查了 tmp 目录的权限,这些都很好(我有 WHM/SSH 访问权限) 所有应该连接到数据库的类都连接得很好,没有问题
请有人让我摆脱痛苦,拯救我剩下的理智!
[编辑][1]
我已经尝试过 w00d 的方法(将session_regenerate_id(true) 设置为false),仍然没有运气)
我也试过完全删除session_regenerate_id(true);,同样的问题仍然存在
[编辑][2]
删除对会话类的调用并使用标准 session_start() 似乎可以“修复”它,但这样做,我不情愿地禁用了数据库系统。
正如我所说,该课程在使用同一服务器的另一个站点上完美运行,那么这里可能存在什么问题?
【问题讨论】: