PHP Session没有携带

时间:2013-12-01 05:59:55

标签: php class session

我知道这已被多次询问过,我已经搜过了SO,尝试了所提供的每种组合以及我能想到的每种方法,而且我仍然处于亏损状态。

以下是该方案: 我刚刚编写并完全测试了登录系统。代码按原样处理,但$_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;
    }
}

userssessions表的数据库结构(使用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()似乎“修复”它,但在这样做时,我不情愿地禁用了数据库系统。

正如我所说的那样,该类在使用相同服务器的另一个站点上完美运行,那么这可能是什么问题呢?

2 个答案:

答案 0 :(得分:0)

问题可能在这里:

    session_regenerate_id(true);

为什么呢? taken here

  

bool session_regenerate_id([bool $ delete_old_session = false])   session_regenerate_id()将使用new替换当前会话ID   一,并保留当前的会话信息。

每次执行start_session时,它都会替换信息。 您可以尝试删除true,看看它是否按预期工作。

答案 1 :(得分:0)

“会话可能正在使用”的原因

会话作业结束后放置硬编码session_write_close();

应该注意register_shutdown_function()不保证session_write_close();正如你所做的那样