Session 工作机制
Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,亦或通过 URL 进行传导。
(1)首先使用session_start()函数进行初始换
(2)当执行PHP脚本时,通过使用$_SESSION超全局变量注册和使用session变量。
(3)当PHP脚本执行结束时,未被销毁的session变量会被自动保存在本地一定路径下的session库中, 这个路径可以通过php.ini文件中的session.save_path指定,下次浏览网页时可以加载使用。
PHP Session 变量
PHP session 变量用于存储有关用户会话的信息,或更改用户会话的设置。Session 变量保存的信息是单一用户的,并且可供应用程序中的所有页面使用。不过,会话信息是临时的,在用户离开网站后将被删除。如果您需要永久储存信息,可以把数据存储在数据库中。
Session 文件
session是以文件的形式保存的。php.ini中有个配置项--session.save_path= "";这个里面填写的路径,将会使session文件保存在该路径下。session文件的命名格式是:"sess_[PHPSESSID的值]"。每一个文件,里面保存了一个会话的数据。其实只要使用代码$_SESSION['user_id'] = $value;就会促发php的session机制,结果往对应的session文件中写入一个值。打开一个session文件,里面就是保存的是一些被序列化后的值。也明白一个知识点,"php圣经"中讲解session的时候,提到session值做被序列化了。下面看到的session内容就是被序列化了。
打开一个session文件,内容如下:
cityID|i:0;cityName|s:3:"all";fanwe_lang|s:5:"zh-cn";fanwe_currency|a:4:{s:2:"id";s:1:"1";s:6:"name_1";s:9:"人民币";s:4:"unit";s:3:"¥";s:5:"radio";s:6:"1.0000";}_fanwe_hash__|s:32:"77c18770c6cb5d89444c407aaa3e8477";
总结出读取规则:
1、每一个session的值是以分号";"分开的。比如“cityID|i:0;cityName|s:3:"all";”就是一个完整的session值结束
2、里面的读取规则:符号“|”前面表示session名称。符号后面是该session的具体信息。包括:数据类型,字符长度,内容。上面第一个就相当于使用如下php代码访问:$_SESSION['cityID']
后面的s表示数据值的类型,3表示字符长度。比如这一段:fanwe_lang|s:5:"zh-cn"; fanwe_lang是变量的名称,变量值是"zh-cn",长度刚好是5,就是”s:5“标明的。
最后"all"就表示session的具体值了。就是使用代码$_SESSION['cityID']后会得到的结果。
3.一个session可以保存一个数组。符号{}表示数组的内容。上面的花括号{}是$_SESSION['fanwe_currency']所保存的内容。要想查看id的值,就使用代码:$_SESSION['fanwe_currency']['id']
Session 使用
具体使用请前往:http://blog.csdn.net/hayley_liu/article/details/52813425
开始Session
session_start()------启动会话,向服务器注册用户的会话,以便可以开始保存用户信息,同时会为用户会话分配一个 UID(名为 PHPSESID的 cookie的值)。即创建一个session,或者恢复当前一个session(基于request请求传递的session_id,这里的值就是http请求时传递的名为PHPSESSID的cookie)(session_start()已经封装了发送cookie的操作(发送一个名称为PHPSESSID的cookie到浏览器),涉及到http的一个原理:头部信息必须在内容之前发送才行即session_start() 函数必须位于 <html> 标签之前)。
session_start()生成一个新的session文件名时,会判断是否存在cookie名为PHPSESSID的值。如果存在,那么就会按照它的值,组合成一个文件名"sess_[phpcookie值]"。所以在目录下,老是能够看到之前删除过的session文件名。如果将浏览器中对应的cookie(PHPSESSID)删掉,那么就不会生成同样的名字了。如果不存在名为PHPSESSID的cookie。php所做的估计为:先发送一个cookie,然后按照cookie的值生成一个(我可以在浏览器中马上看到一个名为PHPSESSID的cookie)
简单来说就是(1)读取名为PHPSESSID(如果没有改变默认值)的cookie值,假使为abc123;(2)若读取到PHPSESSID这个COOKIE,创建$_SESSION变量,并从相应的目录中(可以再php.ini中设置)读取SESS_abc123(默认是这种命名方式)文件,将字符装在入$_SESSION变量中;若没有读取到PHPSESSID这个COOKIE,也会创建$_SESSION变量,同时创建一个sess_abc321(名称为随机值)的session文件,同时将abc321作为PHPSESSID的cookie值返回给浏览器端。
存储Session
存储和取回
session 变量的正确方法是使用 PHP $_SESSION。
例:
<?php session_start(); // store session data $_SESSION['views']=1;
?> <html> <body> <?php //retrieve session data echo "Pageviews=". $_SESSION['views']; ?> </body> </html>
终结Session
unset() 函数用于释放释放当前会话所关联的全局变量。
session_destroy() 销毁当前会话中的全部数据, 但是不会重置当前会话所关联的全局变量, 也不会重置会话 cookie。 如果需要再次使用会话变量, 必须重新调用session_start() 函数。
为了彻底销毁会话,比如在用户退出登录的时候,必须同时重置会话 ID。 如果是通过 cookie 方式传送会话 ID 的,那么同时也需要 调用setcookie() 函数来 删除客户端的会话 cookie。
PHP选择Session文件方式
php是依据,一个名为PHPSESSID的cookie,根据它的值,确定要调用哪个session文件的。去浏览器中,可以看到一个cookie名为PHPSESSID,假如它的值为"sess_adbjsf2q1ass26oootd163sf84",那么,当访问服务器的时候,就会调用session目录下名为"sess_sess_adbjsf2q1ass26oootd163sf84"的文件。其实,PHPSESSID就是一个会话id,以此来确定,哪个是你的会话数据。
以下是在浏览器查看cookie所看到的
cookie的名字PHPSESSID是可以改的,在php.ini中 session.name = PHPSESSID就是设置该cookie的名字。
结合自己实际开发中遇到的问题,总结一下:要说session跟cookie有关联的地方,就是跟PHPSESSID这个cookie有绑定关系。其他,不管你设置什么cookie,使用session的时候是不会用到这些值的。也无法获取到。比如同步登陆,设置即使设置了cookie,而你的应用是依据session判断是否为登陆状态的(事实上也必须如此,因为session保存在服务器端,安全性更高,哪个依据cookie认为你已经登陆,那么很惨)。
所以,这样的情况就会出现,即使成功设置了cookie。也还是不能同步登陆。
同一个Session文件
只要是同一个用户的操作,访问同一个域,导航程序访问记录和团购程序访问的记录都是保存在同一个session文件中。session文件的命名规则是:“sess_PHPSESSID值“。那么,就很容易明白了。因为,客户端存在cookie:PHPSESSID。客户端发送请求后,会将该cookie发送给服务器(php可以使用$_COOKIE['PHPSESSID']看到其内容),这样的话,还是会根据PHPSESSID生成一个session文件的。
如果是不同的域呢?假如用户访问cs.test.com和daohang.test.com,两方程序都设置了session。那么session的结果保存在同一个session文件中吗?
因为:服务器是统一管理session文件的存放的。而php引擎是根据phpsessionid的值确定要操作哪个session文件。session
文件名的格式是:"sess_[phpcookie值]"。依次寻找对应的session文件(于是在浏览器查看名为PHPSESSIONID的cookie,过期时间是在会话结束后)
所以,只要cs.test.com和daohang.test.com使用的是同一台服务器。这样的话,假如是多台服务器的情况。那么就不得不将session保存在数据库中去,这样实现session共享,跟具体的服务器是无关的。
session文件是某个用户整个会话过程中数据。那么,假如cs.test.com和daohang.test.com下的两个程序运行在同一个服务器上。就意味着,访问cs.test.com与访问daohang.test.com是同一个会话。也就意味着,这两边访问后设置的session数据是保存在同一个session文件中的。
Session文件回收
如果”最后的修改时间”到”现在”超过了gc_maxlifetime(默认是1440)秒,这个session文件就被认为是过期了,在下一次session回收的时候,如果这个文件仍然没有被更改过,这个session文件就会被删除(session就过期了)。
简单的说,如果我登录到某网站,如果在1440秒(默认值)内没有操作过,那么对应的session就认为是过期了。 所以,修改php.ini文件中的gc_maxlifetime变量就可以延长session的过期时间了:(例如,我们把过期时间修改为86400秒)
session.gc_maxlifetime = 86400
然后,重启你的web服务(一般是apache)就可以了。
注意1:php5里面session过期使用了回收机制。这里设置时间为86400秒,如果session在86400秒内没有被修改过,那么在下一次“回收”时才真的被删除。
服务器对应的session文件(名为"sess_[phpcookie值]")过期并不是全被删掉。所以才会有session文件很多,出现读取性能的问题。session文件比较多的情况下,产生I/Q读写性能问题。默认情况下,每一次php请求,就会有1/100的概率发生回收,所以可能简单的理解为“每100次php请求就有一次回收发生”。这个概率是通过以下参数控制的
#概率是gc_probability/gc_divisor
session.gc_probability = 1
session.gc_divisor = 100
注意2:假设这种情况gc_maxlifetime=120,如果某个session文件最后修改时间是120秒之前,那么在下一次回收(1/100的概率)发生前,这个session仍然是有效的。
注意3:如果你的session使用session.save_path中使用别的地方保存session,session回收机制有可能不会自动处理过期session文件。这时需要定时手动(或者crontab)的删除过期的session:cd /path/to/sessions; find -cmin +24 | xargs rm
其它
php手册有这句话:
在某些操作系统上,建议使用可以高效处理 大量小尺寸文件的文件系统上的路径来保存会话数据。 例如,在 Linux 平台上,对于会话数据保存的工作而言,reiserfs 文件系统会比 ext2fs 文件系统能够提供更好的性能。
这个是好的方向。session的数据一般很小。适合小文件的文件系统来使用,而我们的传统的文件系统不太适合。
PHP.ini的session配置
;处理session存取的模式(预设:files)
session.save_handler = files
;session档案存放路径(预设:/tmp)
session.save_path = /tmp
;session使用cookie的功能(预设:启动 1)
session.use_cookies = 1
;session的名字(预设:PHPSESSID)
session.name = PHPSESSID
;自动启动(预设:关 0,此处可以改为1)
session.auto_start = 0
;session使用cookie的生存期,以秒为单位(预设:随浏览器关闭而消失 0)
session.cookie_lifetime = 0
;session使用cookie的路径(预设:与domian相同或根路径 /)
session.cookie_path = /
;session使用cookie的域名称(预设:空)
session.cookie_domain =
;处理连续资料的方式,本功能只有WDDX模组或PHP内部使用(预设:php)
session.serialize_handler = php
;按千分之一的比率进行垃圾收集
;垃圾收集的处理几率(预设:1)
session.gc_probability = 1
;设置进程比率,(php5新增参数,预设:1000)
session.gc_divisor = 1000
;(垃圾收集)被处理前的生存期(预设:1440[秒])
session.gc_maxlifetime = 1440
;PHP 4.2和以前的版本都有个BUG,即使你禁止了”允许注册全局变量”.仍然可以让你在全局变量范围中初始化一个SESSION的值
;PHP 4.3 和以后的版本会发出相应的警告,你可以禁止警告.PHP5中,只有你打开了bug_compat_42(=ON),警告才会显示.
session.bug_compat_42,0
session.bug_compat_warn = 1
;session在重新整理时检查session是否还存在(预设:空)
session.referer_check =
;特别设定session值的长度(预设:关)
session.entropy_length = 0
;特别设定session值的文件
session.entropy_file =
;使用cache限制器(预设:不要cache)
session.cache_limiter = nocache
;使用cache的生存期
session.cache_expire = 180
;使用sid值(session_id)传送模式(基于安全,预设:关)
session.use_trans_sid = 0
;选择一个HASH函数,0为MD5(128比特强度),1为SHA-1(160比特强度)
session.hash_function = 0
;定义当转换2进制hash数据为一些可读的数据时,每个字符存储多少个比特.
;4 比特: 0-9, a-f
;5 比特: 0-9, a-v
;6 比特: 0-9, a-z, A-Z, “-”, “,”
session.hash_bits_per_character = 5
;URL重指向的标签
url_rewriter.tags = “a=href,area=href,frame=src,input=src,form=fakeentry”