首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

深入理解 Cookie 与 Session 机制原理及 PHP 实现细节

     編輯:PHP 相關知識

核心区别与联系

特性CookieSession
存储位置客户端浏览器(文件/内存)服务器端(文件/数据库/内存/Redis等)
机制类型客户端维持状态服务器端维持状态
标识传递自动随请求发送依赖 Session ID(通常存 Cookie 或 URL 重写)
安全性可被窃取/篡改/禁用数据不直接暴露给客户端,相对安全
生命周期可设置过期时间,持久化或会话级服务器控制,默认浏览器关闭失效(会话 Cookie)
存储容量单个 ~4KB,域名下共 ~20-50 个受服务器存储限制,理论无上限

联系:Session ID 通常保存在 Cookie 中(名为 PHPSESSID 或 JSESSIONID),浏览器每次请求自动携带,服务器据此关联会话数据。若客户端禁用 Cookie,则需通过 URL 重写或表单隐藏字段传递 Session ID。

Session 机制深度解析

服务端存储结构

服务器使用类似哈希表的结构存储 Session 数据,Key 为 Session ID,Value 为序列化后的会话数据(PHP 默认用文件,键名格式 sess_)。

Session ID 传递方式

  1. Cookie(默认):Set-Cookie: PHPSESSID=abc123; path=/,浏览器自动回传。
  2. URL 重写:
    • 路径参数形式:/page;jsessionid=abc123
    • 查询字符串形式:/page?jsessionid=abc123
  3. 表单隐藏字段:<input type="hidden" name="PHPSESSID" value="abc123">(老旧做法,已少用)。

常见误区:关闭浏览器 Session 就消失了?

错误。 服务器不会因浏览器关闭而立即删除 Session。Session 仅在以下情况被销毁:

  • 程序显式调用 session_destroy()。
  • 超过 session.gc_maxlifetime(默认 1440 秒)未活动,被垃圾回收清理。

“消失”的假象源于:默认 Session ID 存储在会话 Cookie(内存)中,浏览器关闭后 Cookie 丢失,下次访问无法关联原 Session。若将 Cookie 持久化到硬盘或手工携带原 Session ID,依然能恢复会话。

PHP Session 内部工作流程(save_handler = files)

1. session_start() 启动阶段

  1. 垃圾回收概率触发:按 session.gc_probability / session.gc_divisor 概率(默认 1/1000)执行 GC,扫描 session.save_path 下过期文件并删除。
    注意:若 session.save_path 使用 N;/path 分级存储,GC 将失效,需自建 Cron 脚本清理。
  2. 检查 Cookie 中的 Session ID:键名为 session.name(默认 PHPSESSID)。
  3. 无 ID 则生成新 ID,通过 setcookie() 发送到客户端(必须在任何输出前)。
  4. 有 ID 则读取对应文件(sess_),反序列化填充 $_SESSION 超全局数组。

2. 脚本执行阶段

对 $_SESSION 的读写仅在内存中进行,性能极高。

3. 脚本结束写入阶段

将 $_SESSION 序列化写回 Session 文件,关闭资源。此阶段可执行 session_regenerate_id() 更换 ID(常用于登录后提权、防固定攻击)。

4. 销毁 Session 的三种方式

方法效果
setcookie(session_name(), '', time()-8000000, '/')让客户端 Cookie 立即过期,服务端数据暂存
unset($_SESSION)清空当前脚本 $_SESSION,写入空数据,Session 文件仍在
session_destroy()彻底删除 $_SESSION、Session 文件及 Session ID(最彻底)

自定义 Session 处理器(save_handler = user)

通过 session_set_save_handler() 注册六个回调函数,完全接管存储逻辑(如存入 MySQL、Redis、MongoDB)。

<?php
function open($save_path, $session_name) { global $sess_save_path; $sess_save_path = $save_path; return true; }
function close() { return true; }
function read($id) { global $sess_save_path; return (string)@file_get_contents("$sess_save_path/sess_$id"); }
function write($id, $sess_data) { global $sess_save_path; $fp = @fopen("$sess_save_path/sess_$id", "w"); return $fp ? fwrite($fp, $sess_data) : false; }
function destroy($id) { global $sess_save_path; return @unlink("$sess_save_path/sess_$id"); }
function gc($maxlifetime) { global $sess_save_path; foreach (glob("$sess_save_path/sess_*") as $f) { if (filemtime($f) + $maxlifetime < time()) @unlink($f); } return true; }

session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc');
session_start();
// 后续 $_SESSION 操作自动调用上述回调
?>

配置参数速查表

参数默认值说明
session.save_handlerfiles存储驱动:files/user/memcached/redis 等
session.save_path/tmp文件存储路径,支持 N;/path 分级
session.namePHPSESSIDCookie 键名
session.gc_probability1GC 概率分子
session.gc_divisor1000GC 概率分母
session.gc_maxlifetime1440最大生存时间(秒)
session.cookie_lifetime0Cookie 生命周期(0=会话级)
session.cookie_path/Cookie 有效路径
session.cookie_domainCookie 有效域名
session.use_strict_mode0严格模式拒绝未初始化 ID

最佳实践建议

  • 生产环境使用 Redis/Memcached 作为 Session 存储,实现分布式会话共享。
  • 设置 session.cookie_httponly=1 防 XSS 窃取,session.cookie_secure=1 仅 HTTPS 传输。
  • 登录、权限变更时调用 session_regenerate_id(true) 旧 ID 删除,防会话固定攻击。
  • 定期监控 Session 文件数量与 GC 效率,避免 inode 耗尽。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved