从手册去理解分析PHP session机制


Posted in PHP onJuly 17, 2011

session.save_handler = files
1. session_start()

session_start()是session机制的开始,它有一定概率开启垃圾回收,因为session是存放在文件中,PHP自身的垃圾回收是无效的,SESSION的回收是要删文件的,这个概率是根据php.ini的配置决定的,但是有的系统是 session.gc_probability = 0,这也就是说概率是0,而是通过cron脚本来实现垃圾回收。

session.gc_probability = 1 
session.gc_divisor = 1000 
session.gc_maxlifetime = 1440//过期时间 默认24分钟 
//概率是 session.gc_probability/session.gc_divisor 结果 1/1000, 
//不建议设置过小,因为session的垃圾回收,是需要检查每个文件是否过期的。 
session.save_path = //好像不同的系统默认不一样,有一种设置是 "N;/path" 
//这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本

session会判断当前是否有$_COOKIE[session_name()];session_name()返回保存session_id的COOKIE键值,这个值可以从php.ini找到 session.name = PHPSESSID //默认值PHPSESSID

如果不存在会生成一个session_id,然后把生成的session_id作为COOKIE的值传递到客户端.相当于执行了下面COOKIE 操作,注意的是,这一步执行了setcookie()操作,COOKIE是在header头中发送的,这之前是不能有输出的,PHP有另外一个函数 session_regenerate_id() 如果使用这个函数,这之前也是不能有输出的。

setcookie(session_name(), 
session_id(), 
session.cookie_lifetime,//默认0 
session.cookie_path,//默认'/'当前程序跟目录下都有效 
session.cookie_domain,//默认为空 
)

如果存在,那么session_id = $_COOKIE[session_name]; 然后去session.save_path指定的文件夹里去找名字为'SESS_' . session_id()的文件。读取文件的内容反序列化,然后放到$_SESSION中。

2. 为$_SESSION赋值

比如新添加一个值$_SESSION['test'] = 'blah'; 那么这个$_SESSION只会维护在内存中,当脚本执行结束的时候,用把$_SESSION的值写入到session_id指定的文件夹中,然后关闭相关资源。

这个阶段有可能执行更改session_id的操作,比如销毁一个旧的的session_id,生成一个全新的session_id.一半用在自定义 session操作,角色的转换上,比如Drupal.Drupal的匿名用户有一个SESSION的,当它登录后需要换用新的session_id。

if (isset($_COOKIE[session_name()])) { 
setcookie(session_name(), '', time() - 42000, '/');//旧session cookie过期 
} 
session_regenerate_id();//这一步会生成新的session_id 
//session_id()返回的是新的值

3. 写入SESSION操作

在脚本结束的时候会执行SESSION写入操作,把$_SESSION中值写入到session_id命名的文件中,可能已经存在,可能需要创建新的文件。

4. 销毁SESSION

SESSION发出去的COOKIE一般属于即时COOKIE,保存在内存中,当浏览器关闭后,才会过期,假如需要人为强制过期,比如 退出登录,而不是关闭浏览器,那么就需要在代码里销毁SESSION,方法有很多:

setcookie(session_name(), session_id(), time() - 8000000, ..);//退出登录前执行
usset($_SESSION);//这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。
session_destroy();//这个作用更彻底,删除$_SESSION 删除session文件,和session_id
当不关闭浏览器的情况下,再次刷新,2和3都会有COOKIE传过来,但是找不到数据。

session.save_handler = user
用户自定义session处理机制,更加直观 session_set_save_handler('open', 'close', 'read', 'write', 'destroy', 'gc');

session_start(), 执行open($save_path, $session_name)打开session操作句柄。 $save_path 在session.save_handler = files的情况下它就是session.save_path,但是如果用户自定的话,这个两个参数都用不上,直接返回TRUE。执行read($id)从中读取数据.//这个参数是自动传递的就是session_id(),可以通过这个值进行操作。

脚本执行结束,执行write($id, $sess_data) //两个参数,很简单

假如用户需要session_destroy(),先执行destroy,再执行第2步

一个实际例子:

//SESSION初始化的时候调用 
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; 
$sess_file = "$sess_save_path/sess_$id"; 
return (string) @file_get_contents($sess_file); 
} 
//脚本执行结束之前,执行写入操作 
function write($id, $sess_data) 
{ 
echo "sdfsf"; 
global $sess_save_path; 
$sess_file = "$sess_save_path/sess_$id"; 
if ($fp = @fopen($sess_file, "w")) { 
$return = fwrite($fp, $sess_data); 
fclose($fp); 
return $return; 
} else { 
return(false); 
} 
} 
function destroy($id) 
{ 
global $sess_save_path; 
$sess_file = "$sess_save_path/sess_$id"; 
return(@unlink($sess_file)); 
} 
function gc($maxlifetime) 
{ 
global $sess_save_path; 
foreach (glob("$sess_save_path/sess_*") as $filename) { 
if (filemtime($filename) + $maxlifetime < time()) { 
@unlink($filename); 
} 
} 
return true; 
}
PHP 相关文章推荐
基于mysql的论坛(4)
Oct 09 PHP
Windows下的PHP5.0详解
Nov 18 PHP
php定义数组和使用示例(php数组的定义方法)
Mar 29 PHP
php实现的Cookies操作类实例
Sep 24 PHP
PHP函数extension_loaded()用法实例
Jan 19 PHP
PHP的cURL库简介及使用示例
Feb 06 PHP
php函数实现判断是否移动端访问
Mar 03 PHP
PHP  Yii清理缓存的实现方法
Nov 10 PHP
php实现基于pdo的事务处理方法示例
Jul 21 PHP
PHP substr()函数参数解释及用法讲解
Nov 23 PHP
PHP simplexml_load_string()函数实例讲解
Feb 03 PHP
PHP+Redis开发的书签案例实战详解
Jul 09 PHP
php数组的一些常见操作汇总
Jul 17 #PHP
PHP在特殊字符前加斜杠的实现代码
Jul 17 #PHP
PHP的explode和implode的使用说明
Jul 17 #PHP
PHP冒泡排序算法代码详细解读
Jul 17 #PHP
MySQL连接数超过限制的解决方法
Jul 17 #PHP
PHP数组操作汇总 php数组的使用技巧
Jul 17 #PHP
PHP中改变图片的尺寸大小的代码
Jul 17 #PHP
You might like
文件上传类
2006/10/09 PHP
thinkphp实现数组分页示例
2014/04/13 PHP
php中chdir()函数用法实例
2014/11/13 PHP
thinkphp修改配置进入默认首页的方法
2017/02/07 PHP
PHP实现超简单的SSL加密解密、验证及签名的方法示例
2017/08/28 PHP
PHP防止sql注入小技巧之sql预处理原理与实现方法分析
2019/12/13 PHP
快速查找数组中的某个元素并返回下标示例
2013/09/03 Javascript
js获取IFRAME当前的URL的方法
2013/11/13 Javascript
jquery复选框全选/取消示例
2013/12/30 Javascript
JavaScript对IE操作的经典代码(推荐)
2014/03/10 Javascript
js与jquery正则验证电子邮箱、手机号、邮政编码的方法
2016/07/04 Javascript
js实现点击按钮弹出上传文件的窗口
2016/12/23 Javascript
js评分组件使用详解
2017/06/06 Javascript
使用jquery+iframe做一个ajax上传效果(实例)
2017/08/24 jQuery
实例详解BootStrap的动态模态框及静态模态框
2018/08/13 Javascript
js get和post请求实现代码解析
2020/02/06 Javascript
Vue使用路由钩子拦截器beforeEach和afterEach监听路由
2020/11/16 Javascript
[56:41]2018DOTA2亚洲邀请赛 3.31 小组赛 A组 Newbee vs OG
2018/04/01 DOTA
python脚本实现数据导出excel格式的简单方法(推荐)
2016/12/30 Python
Python使用回溯法子集树模板解决爬楼梯问题示例
2017/09/08 Python
轻松理解Python 中的 descriptor
2017/09/15 Python
浅析Python四种数据类型
2018/09/26 Python
django-初始配置(纯手写)详解
2019/07/30 Python
python自动循环定时开关机(非重启)测试
2019/08/26 Python
Python利用Scrapy框架爬取豆瓣电影示例
2020/01/17 Python
python实现百度OCR图片识别过程解析
2020/01/17 Python
Django框架静态文件处理、中间件、上传文件操作实例详解
2020/02/29 Python
优秀团员个人的自我评价
2013/10/02 职场文书
大学生军训自我评价分享
2013/11/09 职场文书
学生会主席就职演讲稿
2014/01/14 职场文书
金融与证券专业求职信
2014/06/22 职场文书
2014迎国庆标语大全
2014/09/19 职场文书
六查六看剖析材料
2014/10/06 职场文书
2015年村计划生育工作总结
2015/04/28 职场文书
签字仪式主持词
2015/07/03 职场文书
docker 制作mysql镜像并自动安装
2022/05/20 Servers