session

本文深入讲解PHP Session的工作原理,包括服务器端与客户端的交互过程、生命周期管理、过期机制及如何自定义存储方式。

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

session

session的基础使用,和服务器数据区(数据存储区:文件、数据库、内存)不冲突。
session的正常声明周期,也就是有效期也是不冲突的,默认是关闭浏览器,或者是1440等。
session_start这个函数是基于php脚本运行的,所以无论是操作$_SESSION这个数组变量(浏览器只存储phpsessid)还是操作数据区,这个将是触发条件。

1、session_start();浏览器请求服务器,服务器去数据区读,判断是否存在,不存在(初始)则初始话一个phpsessid,数据是反序列话的字符串,没有则是空字符。
2、$_SESSION[‘aaaa’]=‘aaa’;  unset($_SESSION);这是在session周期内,无论操作多少次增删$_SESSION,都不影响数据区操作,整个session周期在php脚本中运行,数据区只操作一次读和一次写。
3、脚本执行完,也就是周期外,对数据区进行一个写操作,没有则写,有则修改on duplicate key update或者replace into,这是一个序列化后的字符串有key和value等。
4、响应浏览器设置cookie,存储phpsessid。
以上的是基础session运行机制。
还有就是GC垃圾回收和destroy,都是单独的,比如destroy触发的前提是,在php脚本中需要有代码例如session_start语句:sessiong_destroy();
GC是自动执行的,有一定几率分子分母及max_lifetime,也是需要session_start执行周期内,随机删除过期的或者无操作的session,删除数据区内的。


引用资源:
为什么一段时间后网站后台自动退出 php中session过期时间设置
修改php配置文件中的session.gc_maxlifetime。如果想了解更多session回收机制,继续阅读。(本文环境php5.2)
概述:每一次php请求,会有1/100的概率(默认值)触发“session回收”。如果“session回收”发生,那就会检查/tmp/sess_*的文件,如果最后的修改时间到现在超过了1440秒(gc_maxlifetime的值),就将其删除,意味着这些session过期失效。
1. session在server端(一般是Apache with PHP module)如何存在的?
默认的,php会将session保存在/tmp目录下(Linux系统),文件名为这个样子:sess_01aab840166fd1dc253e3b4a3f0b8381。每一个文件对应了一个session(会话)。
more /tmp/sess_01aab840166fd1dc253e3b4a3f0b8381
username|s:9:”jiangfeng”;admin|s:1:”0″;
#变量名|类型:长度:值
删除这里的session文件,就表示对应的session失效了。
2. session在client端(一般是浏览器)如何存在的?
session在浏览器端,只需要保存session ID(由server端生成的唯一ID)就可以了。有两种保存方式:在cookie中、在url里面。如果cookie中保存session ID,就可以看到浏览器的cookie中有一个PHPSESID变量。如果是URL传递的,就可以看到形如:
index.php?PHPSESID=01aab840166fd1dc253e3b4a3f0b8381的URL。(在server端通过session.use_cookies来控制使用哪一种方式)
3. 在server端,php如何判断session文件是否过期?
如果”最后的修改时间”到”现在”超过了gc_maxlifetime(默认是1440)秒,这个session文件就被认为是过期了,在下一次session回收的时候,如果这个文件仍然没有被更改过,这个session文件就会被删除(session就过期了)。
简单的说,如果我登录到某网站,如果在1440秒(默认值)内没有操作过,那么对应的session就认为是过期了。
所以,修改php.ini文件中的gc_maxlifetime变量就可以延长session的过期时间了:(例如,我们把过期时间修改为86400秒)
session.gc_maxlifetime = 86400
然后,重启你的web服务(一般是apache)就可以了。
注意:php5里面session过期使用了回收机制。这里设置时间为86400秒,如果session在86400秒内没有被修改过,那么在下一次“回收”时才真的被删除。
3. session“回收”何时发生?(moqiang02:下面的【每一次php请求】是指脚本中包含了session操作的请求,例如在另一个浏览器打开含有session_start()的脚本,则原来的session文件被删除)
默认情况下,每一次php请求,就会有1/100的概率发生回收,所以可能简单的理解为“每100次php请求就有一次回收发生”。这个概率是通过以下参数控制的
#概率是gc_probability/gc_divisor
session.gc_probability = 1
session.gc_divisor = 100
注意1:假设这种情况gc_maxlifetime=120,如果某个session文件最后修改时间是120秒之前,那么在下一次回收(1/100的概率)发生前,这个session仍然是有效的。
注意2:如果你的session使用session.save_path中使用别的地方保存session,session回收机制有可能不会自动处理过期session文件。这时需要定时手动(或者crontab)的删除过期的session:cd /path/to/sessions; find -cmin +24 | xargs rm
4. 一些特殊情况
因为回收机制会检查文件的“最后修改时间”,所以如果某个会话是活跃的,但是session的内容没有改变过,那么对应的session文件也就没有改变过,回收机制会认为这是一个长时间没有活跃的session而将其删除。这是我们不愿看到的,可以通过增加如下的简单代码解决这个问题:
<?php
if(!isset($_SESSION['last_access'])||(time()-$_SESSION['last_access'])>60)
 $_SESSION['last_access'] = time();
?>
代码会每隔60秒,尝试修改修改一次session。
总结:如果想修改session过期时间,修改变量gc_maxlifetime就可以了。php5的session采用被动的回收机制(garbage collection)。过期的session文件不会自己消失,而是通过触发“回收”来处理过期的session。

附上SessionDB代码
<?php


/**
 * session入库工具类
 */
class SessionDB{

	private $_dao;

	public function __construct(){

		ini_set('session.save_handler','user');
		session_set_save_handler(
			array($this,'userSessionBegin'),
			array($this,'userSessionEnd'),
			array($this,'userSessionRead'),
			array($this,'userSessionWrite'),
			array($this,'userSessionDelete'),
			array($this,'userSessionGC')
			);
		session_start();
	}

	function userSessionBegin() {
	//初始化数据库服务器连接
		$config = $GLOBALS['config']['db'];

		$this->_dao = MySQLDB::getInstance($config);
	}
	function userSessionEnd() {
		return true;
	}
	/**
	 * 读操作
	 * 执行时机:	session机制开启程中执行
	 * 工作:		从当前session数据区读取内容
	 * @param $sess_id string
	 * @return string
	 */
	function userSessionRead($sess_id) {
		//查询
		$sql = "SELECT session_content FROM `session` WHERE session_id='$sess_id'";
		return (string)$this->_dao->getOne($sql);
	}
	/**
	 * 写操作
	 * 执行时机:	脚本周期结束时,PHP在整理收尾时
	 * 工作:		将当前脚本处理好的session数据,持久化存储到数据库中!
	 * @param $sess_id string
	 * @param $sess_content string 序列化好的session内容字符串
	 * @return bool
	 */
	function userSessionWrite($sess_id, $sess_content) {
		// 完成写
		$sql = "REPLACE INTO `session` VALUES ('$sess_id', '$sess_content', unix_timestamp())";
		// $sql = "INSERT INTO `session` VALUES ('$sess_id', '$sess_content') ON DUPLICATE KEY UPDATE session_content='$sess_content', last_time=unix_timestamp()"
		return $this->_dao->query($sql);
	}
	/**
	 * 删除操作
	 * 执行时机:	调用了session_destroy()销毁session过程中被调用
	 * 工作:		删除当前session的数据区(记录)
	 * @param $sess_id string
	 * @return bool
	 */
	function userSessionDelete($sess_id) {
		//删除
		$sql = "DELETE FROM `session` WHERE session_id='$sess_id'";
		return $this->_dao->query($sql);
	}
	/**
	 * 垃圾回收操作
	 * 执行时机:	开启session机制时,有概率的执行
	 * 工作:		删除那些过期的session数据区
	 * @param $max_lifetime
	 * @return bool
	 */
	function userSessionGC($max_lifetime) {
		//删除
		$sql = "DELETE FROM `session` WHERE last_time<unix_timestamp()-$max_lifetime";
		return $this->_dao->query($sql);
	}

}
笔记



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值