在 CodeIgniter 中恢复 session_id

Posted

技术标签:

【中文标题】在 CodeIgniter 中恢复 session_id【英文标题】:Restore session_id in CodeIgniter 【发布时间】:2011-10-02 18:52:30 【问题描述】:

我想销毁恢复会话 ID,然后启动会话,这是在标准 php 中完成的,如下所示。如何在 CodeIgniter 中做到这一点?

session_destroy();
session_id($old_session_id);
session_start();

我认为会话是通过自动加载库自动启动的:

$autoload['libraries'] = array('session');

是这样吗?如何在 CodeIgniter 中使用session_id($old_session_id);? 我正在尝试$this->session->set_userdata('session_id', $old_session_id);

但似乎有些东西无法正常工作,因为我无法获取会话数据。知道上述几行或其他内容是否有问题? 谢谢。

【问题讨论】:

【参考方案1】:

需要检查的一些事项:

    检查以确保会话在没有 CodeIgniter 的情况下在 PHP 中工作。如果会话不起作用,那么您的服务器没有正确保存会话信息

    检查是否将会话信息保存到数据库中(在 application/config/config.php 中 $config['sess_use_database'] 是否等于 FALSE?如果为 TRUE,则确保将此代码导入你的数据库

 

CREATE TABLE IF NOT EXISTS  `ci_sessions` (
    session_id varchar(40) DEFAULT '0' NOT NULL,
    ip_address varchar(16) DEFAULT '0' NOT NULL,
    user_agent varchar(50) NOT NULL,
    last_activity int(10) unsigned DEFAULT 0 NOT NULL,
    user_data text DEFAULT '' NOT NULL,
    PRIMARY KEY (session_id)
);

如果此处不正确,则 CI 不会保存会话信息。

    在工作的控制器函数中使用这个 sn-p 尝试更多的会话测试:

 

$this->load->library('session'); // load session in controller
echo $session_id = $this->session->userdata('session_id'); // print session id to page

检查您的错误日志以查看 CI 是否正在加载会话库模块并且不存在错误。

这与其说是解决方案,不如说是会话的调试策略。

【讨论】:

【参考方案2】:

CodeIgniter 中的会话与原生 PHP 会话不同。实际上,它们甚至根本不是会话,因为它们实际上是加密的 cookie(您也可以使用数据库来存储会话值,但它们仍然与 php 会话不同)。

引用手册: 什么是会话数据?

A session, as far as CodeIgniter is concerned, is simply an array containing the following information:

    The user's unique Session ID (this is a statistically random string with very strong entropy, hashed with MD5 for portability, and regenerated (by default) every five minutes)
    The user's IP Address
    The user's User Agent data (the first 50 characters of the browser data string)
    The "last activity" time stamp.

The above data is stored in a cookie as a serialized array with this prototype: [array] (
     'session_id'    => random hash,
     'ip_address'    => 'string - user IP address',
     'user_agent'    => 'string - user agent data',
     'last_activity' => timestamp )

每当您加载页面时,CI 都会检查 cookie 以查看那里是否存在会话。如果没有(或者因为你没有设置它,或者因为它已经过期),会话将被创建。相反,如果它在那里,将由 CI 自动生成

如果你想使用 CI 的原生会话,这就是方法。否则,您可以选择原生 php(框架非常灵活),但您不能将两者混合使用,因为它们作用于不同的级别(在服务器上用于 php,在客户端上用于 CI 会话)

【讨论】:

【参考方案3】:

如果有人正在使用遗留的 Codeigniter 项目(如我们)并正在处理这个问题,那么您有一个可能的解决方案(对于会话数据存储在数据库中的情况)。

一旦有了要恢复的 sessionId,就可以从数据库会话表中检索会话数据。此表的 id 对应于您的 sessionId。 您必须反序列化此数据。 然后您可以轻松地恢复会话,将未序列化的数据数组传递给 Codeigniter 会话类的“set_userdata($data)”方法。

这里有一个工作代码示例(请注意,您必须将 $sessionDataFinder 替换为从数据库中检索会话数据的自定义方法,此方法返回一个包含序列化会话数据的字符串,还请注意反序列化方法来自this *** question):

class Restoredatabasesessionlibrary

/** @var CI_Session $session */
private $session;

/** @var CI_Session $session */
private $session;

/** @var Sessiondatafinderlibrary $sessionDataFinder */
private $sessionDataFinder;


public function __construct()

    $ci = &get_instance();

    $ci->load->library(
        [
            'sessiondatafinderlibrary'
        ]
    );

    $this->sessionDataFinder = $ci->sessiondatafinderlibrary;
    $this->session = $ci->session;


/**
 * @throws NotFoundFinderException
 * @throws Exception
 */
public function restoreBySessionId(string $sessionId): void

    $serializedData = $this->sessionDataFinder->getBySessionId($sessionId);

    $data = $this->unserialize($serializedData);

    $this->session->set_userdata($data);


/*
 * Code from: https://***.com/questions/530761/how-can-i-unserialize-session-data-to-an-arbitrary-variable-in-php
 * */
/**
 * @throws Exception
 */
private function unserialize($session_data): array

    $method = ini_get("session.serialize_handler");
    switch ($method) 
        case "php":
            return $this->unserialize_php($session_data);
        case "php_binary":
            return $this->unserialize_phpbinary($session_data);
        default:
            throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary");
    


private function unserialize_php($session_data): array

    $return_data = array();
    $offset = 0;
    while ($offset < strlen($session_data)) 
        if (strpos(substr($session_data, $offset), "|") === false) 
            throw new Exception("invalid data, remaining: " . substr($session_data, $offset));
        
        $pos = strpos($session_data, "|", $offset);
        $num = $pos - $offset;
        $varname = substr($session_data, $offset, $num);
        $offset += $num + 1;
        $data = unserialize(substr($session_data, $offset));
        $return_data[$varname] = $data;
        $offset += strlen(serialize($data));
    

    return $return_data;


private function unserialize_phpbinary($session_data): array

    $return_data = array();
    $offset = 0;
    while ($offset < strlen($session_data)) 
        $num = ord($session_data[$offset]);
        ++$offset;
        $varname = substr($session_data, $offset, $num);
        $offset += $num;
        $data = unserialize(substr($session_data, $offset));
        $return_data[$varname] = $data;
        $offset += strlen(serialize($data));
    

    return $return_data;

【讨论】:

以上是关于在 CodeIgniter 中恢复 session_id的主要内容,如果未能解决你的问题,请参考以下文章

codeigniter 4 设置会话变量 $session = \Config\Services::session();全球

Codeigniter:Session_id 为空

Codeigniter 从 Session 读取值或从 URL 参数读取值哪个更快? [关闭]

SESSION 变量在 Codeigniter php 中的 redirect() 上被重置

codeigniter 覆盖来自非 ci 应用程序的会话数据

$this->session->set_flashdata() 然后 $this->session->flashdata() 在 codeigniter 中不起作用