CI中SESSION的用法及其注意

本文深入解析了CodeIgniter Session类的功能、初始化、数据存储、获取、添加、删除、闪出数据、数据库存储以及销毁过程,详细阐述了如何在Web开发中高效利用Session类来维护用户状态和跟踪行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Session 类
Session类可以使用户在浏览您的网站时,维持他们的状态并跟踪他们的行为。 Session类将每个用户的session信息序列化(serialize)后存储到到cookie中(并同时进行加密)。您还可以将session数据存储到数据库中来增强安全性,但是这时要求存储在用户cookie中的session ID值能与数据库中存储的用户session ID值相匹配。程序默认只在cookie中存储session。如果您在要在数据库中存储session的话,需要按照下面指示的方法,在您的数据库中创建需要的数据表。

注意: Session类并不使用PHP本身的session,而是使用类自己的session,这样做,可以给开发者提供更大的弹性。

初始化 Session
Sessions会在每个页面载入后开始运行,所以session类必须首先被初始化。您可以在控制器中初始化,也可以在系统中自动加载(译者注:在autoload.php设定)。session类的绝大部分都会在后台运行,所以初始化session时,它session数据会被自动读取、创建和更新。

要在您的控制器构造函数中初始化session类,您可以使用 $this->load->library 函数:

$this->load->library(‘session’);

一旦被载入, session就可以这样使用: $this->session

Sessions 是怎样工作的?
当页面载入后,session类就会检查用户的cookie中是否存在有效的session数据。如果session数据不存在(或者已经过期),那么就会创建一个新的session并把他保存在cookie中。如果session数据存在,那么他的信息就会被更新,同时cookie也会被同时更新。每次更新都会重新生成session_id的值。

对于您来说,需要知道的非常重要的一点就是,session类一旦被初始化,它就会自动运行。对于后面的事情,您可以完全不作理会。正如您将会在下面看到的一样,您可以正常使用session来工作,甚至还可以添加自己的session数据,而在这一切的过程中,读、写和更新的操作都是自动完成的。

Session 数据是什么?
一个 session 是由一个包括下列信息的数组组成的:

唯一的用户Session ID (这是一个平均信息量统计出来的非常坚固的随机字符串,使用MD5加密,默认是每五分钟就重新生成一次。
用户的 IP 地址
用户浏览器信息(取前50个字符)
最新的一个活跃时间戳.
以上数据将会用以下数组格式序列化并存到cookie里:

[array]
(
‘session_id’ => random hash,
‘ip_address’ => ‘string – user IP address’,
‘user_agent’ => ‘string – user agent data’,
‘last_activity’ => timestamp
)

如果你将加密设置开启,serialized 的数组会被先被加密,然后存入cookie中。这会让数据不容易被看到和修改,从而提高安全性。从这里可以找到更多关于加密的信息。Session类会自动负责初始化和数据加密。

注意: 默认情况下, Session Cookie 每隔 5 分钟才会更新一次,这样会减少对处理器的负荷。如果你重复的装载页面, 你会发现”上次活动”的时间在五分钟,或多余五分钟的时候才会变化,也就是 cookie 上次被写入的时间。 这个时间可以通过设置 system/config/config.php 文件里的 $config['time_to_update'] 行来改变。

取得 Session 数据
可以通过如下的函数来得到 session 数组的任何信息:

$this->session->userdata(‘item’);

item 是数组里的相对应数据的索引。例如,想要获得 session ID, 你要使用如下的代码:

$session_id = $this->session->userdata(‘session_id’);

注意: 如果你的目标数据不存在的话,这个函数会返回 FALSE (布尔值boolean)。

添加自定义的 Session 数据
session 数组的一个非常有用的用途是你可以它里面添加你自己的数据,这些数据会被保存在用户的 cookie 中。这样做的原因是什么呢?看看这个例子:

假设,有个特定用户登陆到你的网站, 当他通过检测后 你可以添加他的用户名和电子邮件到 session cookie 中,这些信息可以在不去访问数据库的情况下,当成全局量来使用。

通过以下函数,你可以传递一个新的用户数组到 session 数组中:

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

$array 是一个结合数组,用来存储你的新数据。例如 :

$newdata = array(
‘username’ => ‘johndoe’,
‘email’ => ‘johndoe@some-site.com’,
‘logged_in’ => TRUE
);

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

如果使用下面 set_userdata()函数的写法,可以每次只添加一个用户数据。

$this->session->set_userdata(‘some_name’, ‘some_value’);

注意: Cookies 只能存储 4KB 的数据, 使用时要小心超出它的容量。特别指出的是,加密会产生比原数据更长的数据字符串,所以一定要当心你要存放数据的大小。

删除 Session 数据
正如使用 set_userdata() 是用来添加信息到 session 中,而通过向 unset_userdata() 函数中传递 session key 可以用来删除这些信息。例如, 你想要从 session 信息里去掉 ‘some_name’:

$this->session->unset_userdata(‘some_name’);


也可以给这个函数传一个要删除项的关联数组。

$array_items = array(‘username’ => ”, ‘email’ => ”);

$this->session->unset_userdata($array_items);

闪出数据
CodeIgniter 支持 “闪出数据”, 或者说Session数据只对下次服务器请求可用, 然后会自动清除。这应该会非常有用,往往应用在信息或状态提示中(例如:“记录2已删除”)。

注意: 闪出数据变量名以“flash_”开头,所以在你自己的变量名中要避免使用这个前缀。

要添加闪出数据:

$this->session->set_flashdata(‘item’, ‘value’);

你也可以使用和 set_flashdata() 同样的方式向 set_flashdata() 传递一个数组。

要读取一个闪出数据变量:

$this->session->flashdata(‘item’);

如果你发现你需要在一个附加的请求中保留一个闪出数据,你可以使用 keep_flashdata() 这个函数。

$this->session->keep_flashdata(‘item’);

将 Session 数据存入数据库
由于Session数据数组是附带一个Session ID保存在用户cookie里的,你无法验证它,除非你把session数据存储在数据库中。在一些不需要或很少需要安全保护的应用中,session ID 或许并不需要。但如果你的应用需要安全保护,验证是必须滴。

当session 数据在数据库中可用时,每当从用户cookie中发现一个有效的session,一个数据库查询就会被执行以匹配它。如果 session ID 不相配,session 就会被销毁。Session ID永远不会更新,它们只会在一个新的会话创建时生成。

为了存储session,你必须先创建一个数据表。这是 session 类所需的基本结构(用于MySQL的):

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 NOT NULL,
PRIMARY KEY (session_id)
);
注意: 默认情况下这个表叫做 ci_sessions, 但是你可以给它指定任意名字,只要你更新了 application/config/config.php 文件以确保它包含了你所起的名字。一旦你创建了数据表,你就可以像下面这样在config.php文件中启用数据库选项:

$config['sess_use_database'] = TRUE;

一旦启用了,Session类就会在数据库中存储session数据。

同时确保你已经在配置文件中指定了数据表名:

$config['sess_table_name'] = ‘ci_sessions”;

注意: Session类已经内置了清除过期session的垃圾回收机制,因此你不需要编写你自己的事务来做这个。

销毁 Session
要清除当前 session:

$this->session->sess_destroy();

注意: 此函数应该是最后被调用的。即使闪出变量已不再有效。如果你只想让某几项而不是所有项被销毁,请使用 unset_userdata().


Session 的参数
你可以在application/config/config.php 文件中找到以下的 Session 相关的参数:

参数 默认 选项 描述
sess_cookie_name ci_session 无 你想要保存 Session Cookie 的名字。
sess_expiration 7200 无 session 持续的秒数。默认是2个小时(7200秒)。如果将这个数值设为: 0,就可以得到 永久 session。
sess_encrypt_cookie FALSE TRUE/FALSE (布尔值boolean) 是否对 session 数据加密.
sess_use_database FALSE TRUE/FALSE (布尔值boolean) 是否将 session 数据存放入数据库中。在开启这个选项前,你要先创建一个数据库表。
sess_table_name ci_sessions 任何有效的 SQL 表名 session 数据库表的名字。
sess_time_to_update 300 时间以秒计算 这个选项控制 session 类多久会产生一个新的session 和 session id。
sess_match_ip FALSE TRUE/FALSE (布尔值boolean) 是否通过用户的IP地址来读取 session 的数据。 注意 ,有些网络运行商 ISPs 会动态的改变IP, 所以将这个选项设为 FALSE, 才有可能得到永久的 session。
sess_match_useragent TRUE TRUE/FALSE (布尔值boolean) 是否要按照对应的 User Agent 来读取 session 数据。

<think>好的,我现在需要解决用户关于Windows 11系统级会话中任务计划程序以SYSTEM权限运行的进程的会话信息的问题。用户之前已经询问过系统级会话和用户登录会话的区别以及相关的C++实现,现在需要更具体的信息,特别是任务计划程序和SYSTEM权限进程的会话情况。 首先,我得确认用户的问题核心:任务计划程序中以SYSTEM权限运行的进程属于哪个会话?根据之前的知识,系统级会话是Session 0,而用户会话从Session 1开始。但可能需要验证这一点,尤其是在Windows 11中是否有变化。 接下来,我需要考虑如何获取这些进程的会话信息。用户之前提供的引用是关于SQL查询的,但当前问题涉及系统进程,可能需要使用命令行工具或PowerShell命令。例如,使用tasklist命令或者PowerShell的Get-ScheduledTask和Get-Process组合。 然后,需要确定SYSTEM权限进程在任务计划程序中的运行环境。任务计划程序可以配置运行身份为用户或SYSTEM,这些进程在Session 0中运行,因为它们属于系统服务。但需要确认Windows 11是否仍然遵循此模式,或者是否有新的变化。 另外,用户可能想知道如何以编程方式获取这些信息,比如用C++或C#。可能需要调用Windows API函数,如WTSEnumerateProcesses或QueryFullProcessImageName,来获取进程的会话ID。 还要注意用户之前提到的安全增强,比如HVCI和虚拟化安全,这些是否会影响进程会话的查看或管理。例如,某些高权限进程可能被隔离,导致传统方法无法获取其信息。 最后,用户可能需要具体的步骤或代码示例来实际获取会话信息,因此需要提供清晰的命令行示例和可能的代码片段,同时确保引用之前的回答内容,如使用WTSQuerySessionInformation或ProcessIdToSessionId函数。</think>### Windows 11 系统级会话中计划任务进程的会话信息查询指南 --- #### 一、核心原理分析 1. **SYSTEM权限进程特征** - 始终运行在Session 0(系统级会话) - 无用户界面且与桌面环境隔离[^4] - 通过任务计划程序创建时会默认继承SYSTEM上下文 2. **Windows 11 会话机制更新** - 新增`Session 0 Isolation`安全机制,强化系统进程隔离 - 计划任务详情中新增`SessionId`字段标识[^6] --- #### 二、快速查询方法 ##### 方法1:通过PowerShell验证 ```powershell # 查询所有计划任务及其会话信息 Get-ScheduledTask | ForEach-Object { $task = $_ $principal = $_.Principal if ($principal.UserId -eq "SYSTEM") { [PSCustomObject]@{ TaskName = $task.TaskName SessionID = $task.SessionId Command = ($task.Actions | Select-Object -ExpandProperty Execute) } } } | Format-Table -AutoSize ``` 输出示例: ``` TaskName SessionID Command -------- --------- ------- SystemScanTask 0 C:\Windows\System32\scan.exe ``` ##### 方法2:通过任务计划程序GUI 1. 按`Win+R`输入`taskschd.msc` 2. 右键任务 -> 属性 -> 常规选项卡 3. 查看"安全选项"中的运行账户为`SYSTEM` 4. 详细信息选项卡查看会话ID字段 --- #### 三、编程实现方案(C++) ##### 1. 获取计划任务进程列表 ```cpp #include <taskschd.h> #pragma comment(lib, "taskschd.lib") void ListSystemTasks() { ITaskService* pService = nullptr; CoInitializeEx(nullptr, COINIT_MULTITHREADED); CoCreateInstance(CLSID_TaskScheduler, nullptr, CLSCTX_INPROC_SERVER, IID_ITaskService, (void**)&pService); pService->Connect(_variant_t(), _variant_t(), _variant_t(), _variant_t()); ITaskFolder* pRootFolder = nullptr; pService->GetFolder(_bstr_t(L"\\"), &pRootFolder); IRegisteredTaskCollection* pTasks = nullptr; pRootFolder->GetTasks(TASK_ENUM_HIDDEN, &pTasks); LONG count = 0; pTasks->get_Count(&count); for (LONG i = 0; i < count; ++i) { IRegisteredTask* pTask = nullptr; pTasks->get_Item(_variant_t(i + 1), &pTask); ITaskDefinition* pDefinition = nullptr; pTask->get_Definition(&pDefinition); IPrincipal* pPrincipal = nullptr; pDefinition->get_Principal(&pPrincipal); BSTR userId = nullptr; pPrincipal->get_UserId(&userId); if (wcscmp(userId, L"SYSTEM") == 0) { // 获取会话ID ITaskSettings3* pSettings = nullptr; pDefinition->get_Settings(&pSettings); LONG sessionId = 0; pSettings->get_SessionId(&sessionId); std::wcout << L"Session ID: " << sessionId << std::endl; } } } ``` ##### 2. 验证进程实际会话状态 ```cpp #include <WtsApi32.h> #pragma comment(lib, "Wtsapi32.lib") void CheckProcessSession(DWORD pid) { DWORD sessionId = 0; if (ProcessIdToSessionId(pid, &sessionId)) { WTSINFOEX* pInfo = nullptr; DWORD bytesReturned = 0; if (WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, sessionId, WTSSessionInfoEx, (LPWSTR*)&pInfo, &bytesReturned)) { if (pInfo->Level == 1) { std::wcout << L"会话类型: " << (pInfo->Data.WTSInfoExLevel1.SessionFlags == 0 ? L"系统会话" : L"用户会话") << std::endl; } WTSFreeMemory(pInfo); } } } ``` --- #### 四、高级调试技巧 ##### 1. 使用Process Explorer验证 1. 下载Sysinternals Process Explorer 2. 启用`View -> Show Processes from All Users` 3. 查找SYSTEM账户进程 4. 双击进程查看属性窗口的`Session`字段 ![Process Explorer示例](https://i.imgur.com/ZYHpQ9l.png) ##### 2. 通过事件日志追踪 ```powershell # 查询计划任务相关事件 Get-WinEvent -LogName Microsoft-Windows-TaskScheduler/Operational | Where-Object { $_.Properties[6].Value -eq "SYSTEM" } | Select-Object TimeCreated, Message ``` --- #### 五、安全注意事项 1. **会话隔离原则** - SYSTEM进程无法直接与用户会话交互 - 跨会话通信必须使用命名管道/RPC等安全通道 2. **权限提升风险** - 修改系统级会话任务需`Administrator`权限 - 建议使用`CreateRestrictedToken`创建降权令牌[^5] ```cpp // 创建受限令牌示例 HANDLE CreateLimitedToken() { HANDLE hToken; OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken); TOKEN_PRIVILEGES tp; tp.PrivilegeCount = 0; // 移除所有特权 HANDLE hNewToken; CreateRestrictedToken(hToken, DISABLE_MAX_PRIVILEGE, 0, nullptr, 0, nullptr, 0, nullptr, &hNewToken); return hNewToken; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值