PHP session机制小析
2015-06-28 15:09
543 查看
经常遇到一些用PHP写的需要登录的网站,如果你想退出,一个很方便的做法就是如下图所示:
在浏览器那里,按下F12,找的Cookies那一项,然后把名为PHPSESSID的Cookie删掉,然后刷新一下页面,你就会发现,自己已经退出了。这是什么原因呢?因为我们知道,PHP网站判断是否登录一般是用session来判断的,那为什么删除了Cookie之后就退出了呢?那么,我们就要知道,删除了这个Cookie对session到底有什么影响。
首先,我们需要知道,PHP是如何实现session机制的呢。当我们进入一个PHP网站,这个网站第一次执行session_start();时,PHP内部其实是执行了如下过程:
这段代码其实就是设置了一个Cookie,这个Cookie的key是ini_get(‘session.name’)(一般我们的PHP配置文件里面,session.name的值默认是PHPSESSID),这个Cookie的value是session_id()(session_id()会生成一串字符串,在上面那个图中,这个字符串就是:’uqafv5lgqdm68nuvbp6kdprd66’)。
接着,网站可能会设置session的值。如下:
那么这之后程序会做什么呢?PHP内部会在程序结束之前,将session这个变量序列化后存放到一个文件中(假设PHP配置文件中session.save_handler = files),这个文件所在的目录就是session.save_path定义的目录,文件名就是”sess_”.session_id();(比如上图那个用户,session_id() = ‘uqafv5lgqdm68nuvbp6kdprd66’;在PHP配置文件中,定义了session.save_path = “c:/wamp/tmp”,所以就可以看到有这么一个文件存在。)
设置好session之后,当用户第二次再访问该站点的时候,后端程序根据用户传上来的Cookie中PHPSESSID的值,获取到该用户session文件,然后将文件中的内容反序列化后,赋给$_SESSION变量。到这里,就可以理解,为什么删除了Cookie里面的PHPSESSID,用户就会退出了吧。
到这里,再讲一下session的失效和垃圾回收机制。在session_start()函数中,会先将session文件里面的内容序列化给$_SESSION变量,然后再按一定的概率执行session的垃圾回收函数。这个顺序很重要,等下再讲为什么。这里执行session垃圾回收的概率等于:session.gc_probability / session.gc_divisor。session的垃圾回收函数可以大致理解如下过程:
垃圾回收过程简单的说就是:获取目录下所有以”sess_”开头的文件,如果上次修改时间离当前时间超过session的有效时间,就将该文件删除。删除session文件之后,用户再来访问,由于session里面的内容没有了,用户就自然变成退出状态了。
最后说一点,如果我们设置session.gc_maxlifetime = 600;那么,当一个用户600秒后才再次刷新页面,是不是一定会被退出呢?答案是:不一定。这要看在这个用户刷新页面时,之前的用户请求有没有触发session垃圾回收函数,如果触发了,用户会被退出,如果没有,就不会被退出。但如果,就在用户刷新页面的那次请求里,触发了session的垃圾回收函数,那用户会被退出吗?答案是:不会的。因为刚才说过,session的垃圾回收函数是在PHP获取了session内容后执行的。所以,虽然用户的session文件已经失效,但是由于在用户获取session数据的时候,session文件并没有被删除,所以用户不会被退出。
在浏览器那里,按下F12,找的Cookies那一项,然后把名为PHPSESSID的Cookie删掉,然后刷新一下页面,你就会发现,自己已经退出了。这是什么原因呢?因为我们知道,PHP网站判断是否登录一般是用session来判断的,那为什么删除了Cookie之后就退出了呢?那么,我们就要知道,删除了这个Cookie对session到底有什么影响。
首先,我们需要知道,PHP是如何实现session机制的呢。当我们进入一个PHP网站,这个网站第一次执行session_start();时,PHP内部其实是执行了如下过程:
setcookie(ini_get('session.name'), session_id(), ini_get('session.cookie_lifetime'),//默认0 ini_get('session.cookie_path'),//默认'/'当前程序根目录下都有效 ini_get('session.cookie_domain')//默认为空 );
这段代码其实就是设置了一个Cookie,这个Cookie的key是ini_get(‘session.name’)(一般我们的PHP配置文件里面,session.name的值默认是PHPSESSID),这个Cookie的value是session_id()(session_id()会生成一串字符串,在上面那个图中,这个字符串就是:’uqafv5lgqdm68nuvbp6kdprd66’)。
接着,网站可能会设置session的值。如下:
$_SESSION['name'] = 'tihouzai'; $_SESSION['telnum'] = 12345678910;
那么这之后程序会做什么呢?PHP内部会在程序结束之前,将session这个变量序列化后存放到一个文件中(假设PHP配置文件中session.save_handler = files),这个文件所在的目录就是session.save_path定义的目录,文件名就是”sess_”.session_id();(比如上图那个用户,session_id() = ‘uqafv5lgqdm68nuvbp6kdprd66’;在PHP配置文件中,定义了session.save_path = “c:/wamp/tmp”,所以就可以看到有这么一个文件存在。)
设置好session之后,当用户第二次再访问该站点的时候,后端程序根据用户传上来的Cookie中PHPSESSID的值,获取到该用户session文件,然后将文件中的内容反序列化后,赋给$_SESSION变量。到这里,就可以理解,为什么删除了Cookie里面的PHPSESSID,用户就会退出了吧。
到这里,再讲一下session的失效和垃圾回收机制。在session_start()函数中,会先将session文件里面的内容序列化给$_SESSION变量,然后再按一定的概率执行session的垃圾回收函数。这个顺序很重要,等下再讲为什么。这里执行session垃圾回收的概率等于:session.gc_probability / session.gc_divisor。session的垃圾回收函数可以大致理解如下过程:
$session_path = rtrim(ini_get('session.save_path'),'/'); $maxLiftTime = ini_get('session.gc_maxlifetime'); //session的有效时间 $time = time(); foreach(glob($session_path.'/sess_*') as $file){ if(filemtime($file) + $maxLiftTime < $time){ @unlink($file); } }
垃圾回收过程简单的说就是:获取目录下所有以”sess_”开头的文件,如果上次修改时间离当前时间超过session的有效时间,就将该文件删除。删除session文件之后,用户再来访问,由于session里面的内容没有了,用户就自然变成退出状态了。
最后说一点,如果我们设置session.gc_maxlifetime = 600;那么,当一个用户600秒后才再次刷新页面,是不是一定会被退出呢?答案是:不一定。这要看在这个用户刷新页面时,之前的用户请求有没有触发session垃圾回收函数,如果触发了,用户会被退出,如果没有,就不会被退出。但如果,就在用户刷新页面的那次请求里,触发了session的垃圾回收函数,那用户会被退出吗?答案是:不会的。因为刚才说过,session的垃圾回收函数是在PHP获取了session内容后执行的。所以,虽然用户的session文件已经失效,但是由于在用户获取session数据的时候,session文件并没有被删除,所以用户不会被退出。
相关文章推荐
- FTP服务器搭建
- zend 快捷键
- Laravel5.1 学习笔记1, 目录结构和命名空间(待修)
- A Brief Introduction to PHP Namespacing
- PHP中的魔术方法和魔术常量
- 系统吞吐量、TPS(QPS)、用户并发量、性能测试概念和公式
- PHP命令行下的世界
- Yii查询生成器(Query Builder)用法实例教程
- vsftpd.conf 详解与实例配置
- YII-1.16增加注册模块
- 使用php搭建自己的MVC框架
- php socket 处理不过来数据流,该如何避免(好像是阻塞了)
- 基于CakePHP实现的简单博客系统实例
- php namespace 和composer
- 【翻译自nikic大神】PHP中原生类型的方法
- 转载 PHP学习笔记 - 在Eclipse中使用XDebug调试代码 | Using XDebug debug code in eclipse
- 探讨PHP simplexml详细使用方法
- php页面静态化—静态化详细介绍
- php页面静态化—优化页面响应时间
- 解决安装laravel/homestead vagrant环境报"A VirtualBox machine with the name 'homestead' already exists."的错误