【问题标题】:PHP Session not carryingPHP Session 没有携带
【发布时间】: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;
    }
}

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() 似乎可以“修复”它,但这样做,我不情愿地禁用了数据库系统。

正如我所说,该课程在使用同一服务器的另一个站点上完美运行,那么这里可能存在什么问题?

【问题讨论】:

    标签: php class session


    【解决方案1】:

    问题可能在这里:

        session_regenerate_id(true);
    

    为什么? taken here

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

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

    【讨论】:

    • 设置为 false 会返回相同的问题。不过还是谢谢
    • 为什么要重新生成id?看到这个stackoverflow.com/questions/19656129/…
    • 主要是为了使数据库保持最新并清除多个条目。
    • 你能做一个最简单的例子:删除所有会话设置,只删除 session_start() 并检查你的会话吗?还打印session_save_path() 并检查该目录。如果正确,您应该会看到一些以 session_id 为名称的文件,看看是否存储了任何数据
    • 澄清一下:您要求我删除对类的任何调用并改用 PHP 的原生 session_start?如果是这样,完成并完美运行。这意味着......嗯......原来的帖子更新了
    【解决方案2】:

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

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

    需要注意的是register_shutdown_function()不保证session_write_close();正如你所做的那样

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-09
      • 2017-08-09
      • 2019-08-13
      • 1970-01-01
      • 2011-04-22
      相关资源
      最近更新 更多