深入讲解PHP Session及如何保持其不过期的方法

SESSION的实现中采用COOKIE技术,SESSION会在客户端保存一个包含session_id(SESSION编号)的COOKIE;在服务器端保存其他session变量,比如session_name等等。当用户请求服务器时也把session_id一起发送到服务器,通过
session_id提取所保存在服务器端的变量,就能识别用户是谁了。同时也不难理解为什么SESSION有时会失效了。

Session的声明与使用

当客户端禁用COOKIE时(点击IE中的“工具”―“Internet选项”,在弹出的对话框里点击“安全”―“自定义级别”项,将“允许每个对话COOKIE”设为禁用),session_id将无法传递,此时
SESSION失效。不过php5在linux/unix平台可以自动检查cookie状态,如果客户端设置了禁用,则系统自动把session_id附加到url上传递。windows主机则无此功能。

Session的设置不同于Cookie,必须先启动,在PHP中必须调用session_start()。session_start()函数的语法格式如下:

Session常见函数及用法?Session_start()
:开始一个会话或者返回已经存在的会话。说明:这个函数没有参数,且返回值均为true。如果你使用基于cookie的session(cookie-based
sessions),那么在使用Session_start()之前浏览器不能有任何输出,否则会发生以下错误:Warning:
Cannot send session cache limiter – headers already sent (output started
at /usr/local/apache/htdocs/cga/member/1.php:2)…………

Bool session_start(void)          
//创建Session,开始一个会话,进行Session初始化

你可以在php.ini里启动session.auto_start=1,这样就无需每次使用session之前都要调用session_start()。但启用该选项也有一些限制,如果确实启用了
session.auto_start,则不能将对象放入会话中,因为类定义必须在启动会话之前加载以在会话中重建对象。请求结束后所有注册的变量都会被序列化。已注册但未定义的变量被标记为未定义。在之后的访问中这些变量也未被会话模块定义,除非用户以后定义它们。

注意:session_start()函数之前不能有任何输出

警告: 有些类型的数据不能被序列化因此也就不能保存在会话中。包括 resource
变量或者有循环引用的对象。

当第一次访问网站时,Seesion_start()函数就会创建一个唯一的Session

注册SESSION变量
:PHP5使用$_SESSION[‘xxx’]=xxx注册SESSION全局变量。和GET,POST,COOKIE的使用方法相似。注意:session_register(),session_unregister
,session_is_registered在php5下不再使用,除非在php.ini里把register_globle设为on,不过出于安全考虑,强烈建议关闭register_globle。HTTP_SESSION_VARS也不提倡使用了,官方建议用$_SESSION代替之。例如:

ID,并自动通过HTTP的响应头,将这个Session
ID保存到客户端Cookie中。同时,也在服务器端创建一个以Session
ID命名的文件,用于保存这个用户的会话信息。当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将Cookie中保存的Seesion
ID再携带过来,这时Session_start()函数就不会再去分配一个新的Session
ID,而是在服务器的硬盘中去寻找和这个Session

Page1.php

ID同名的Session文件,将这之前为这个用户保存的会话信息读出,在当前脚本中应用,达到跟踪这个用户的目的。

 php Session_start(); //使用SESSION前必须调用该函数。 $_SESSION[‘name']=”我是黑旋风李逵!”; //注册一个SESSION变量 $_SESSION[‘passwd']=”mynameislikui”; $_SESSION[‘time']=time(); echo ' 通过COOKIE传递SESSION'; //如果客户端支持cookie,可通过该链接传递session到。 echo ' . SID . '"通过URL传递SESSION';//客户端不支持cookie时,使用该办法传递session. 

Session以数组的形式使用,如:$_SESSION[‘session名’]

Page2.php

注册一个会话变量和读取Session

 php session_start(); echo $_SESSION['name']; // echo $_SESSION['passwd']; // echo date('Y m d H:i:s', $_SESSION['time']); echo ' 返回山一页'; 

在PHP中使用Session变量,除了要启动之外,还要经过注册的过程。注册和读取Session变量,都要通过访问$_SESSION数组完成。在$_SESSION关联数组中的键名具有和PHP中普通变量相同的命名规则。注册Session变量的代码如下所示:

有两种方法传递一个会话 ID:

//启动session的初始化

cookie URL 参数

session_start();

会话模块支持这两种方法。cookie
更优化,但由于不总是可用,也提供替代的方法。第二种方法直接将会话 ID
嵌入到 URL 中间去。

//注册session变量,赋值为一个用户的名称

PHP 可以透明地转换连接。除非是使用 PHP 4.2 或更新版本,需要手工在编译
PHP 时激活。在 Unix 下,用 –enable-trans-sid
配置选项。如果此配置选项和运行时选项 session.use_trans_sid
都被激活(修改php.ini),相对 URI 将被自动修改为包含会话 ID。

$_SESSION[“username”]=”skygao”;

session_idsession_id()
用于设定或取得当前session_id。php5中既可以使用session_id(),也可以通过附加在url上的SID取得当前会话的session_id和session_name。如果session_id()有具体指定值的话,将取代当前的session_id值。使用该函数前必须启动会话:session_start();当我们使用session
cookies时,如果指定了一个session_id()值,每次启动session_start()都会往客户端发送一个cookie值。不论当前session_id是否与指定值相等。session_id()如果没有指定值,则返回当前session_id();当前会话没有启动的话,则返回空字符串。

//注册session变量,赋值为一个用户的ID

检查session是否存在?在以往的php版本中通常使用session_is_register()检查session是否存在,如果您使用$_SESSION[澳门新葡亰平台官网,‘XXX’]=XXX来注册会话变量,则session_is_register()函数不再起作用。你可以使用isset($_SESSION[‘xxx’])来替代。

$_SESSION[“uid”]=1;

更改session_id session_regenerate_id()
更改成功则返回true,失败则返回false。使用该函数可以为当前session更改session_id,但不改变当前session的其他信息。例如:

?>

 php session_start(); $old_sessionid = session_id(); session_regenerate_id(); $new_sessionid = session_id(); echo "原始 SessionID: $old_sessionid "; echo "新的 SessionID: $new_sessionid "; echo" "; print_r($_SESSION); echo""; 

执行该脚本后,两个Session变量就会被保存在服务器端的某个文件中,该文件的位置是通过php.ini文件,在session.save_path属性指定的目录下。

session_name()
返回当前session的name或改变当前session的name。如果要改变当前session的name,必须在session_start()
之前调用该函数。注意:session_name不能只由数字组成,它至少包含一个字母。否则会在每时每刻都生成一个新的session
id.session改名示例:

注销变量与销毁Session

$previous_name = session_name("WebsiteID");echo "新的session名为: $previous_name";

当使用完一个Session变量后,可以将其删除,当完成一个会话后,也可以将其销毁。如果用户退出Web系统,就需要为他提供一个注销的功能,把他的所有信息在服务器中销毁。销毁和当前Session有关的所有的资料,可以调用session_destroy()函数结束当前的会话,并清空会话中的所有资源。该函数的语法格式如下所示:

如何删除session?1、unset ($_SESSION[‘xxx’])
删除单个session,unset($_SESSION[‘xxx’])
用来unregister一个已注册的session变量。其作用和session_unregister()相同。
session_unregister()在PHP5中不再使用,可将之打入冷宫。unset($_SESSION)
此函数千万不可使用,它会将全局变量$_SESSION销毁,而且还没有可行的办法将其恢复。用户也不再可以注册$_SESSION变量。2、$_SESSION=array()
删除多个session3、
session_destroy()结束当前的会话,并清空会话中的所有资源。。该函数不会unset(释放)和当前session相关的全局变量
(globalvariables),也不会删除客户端的session
cookie.PHP默认的session是基于cookie的,如果要删除cookie的话,必须借助setcookie()函数。返回值:布尔值。功能说明:这个函数结束当前的session,此函数没有参数,且返回值均为true

bool session_destroy(void)     //销毁和当前Session有关的所有资料

session_unset()
如果使用了$_SESSION,则该函数不再起作用。由于PHP5必定要使用$_SESSION,所以此函数可以打入冷宫了。

该函数并不会释放和当前Session相关的变量,也不会删除保存在客户端Cookie中的Session
ID。因为$_SESSION数组和自定义的数组在使用上是相同的,所以我们可以使用unset()函数来释放在Session中注册的单个变量。如下所示:

下面是PHP官方关于删除session的案例:

unset($_SESSION[‘键名’]);

 php // 初始化session. session_start(); /*** 删除所有的session变量..也可用unset($_SESSION[xxx])逐个删除。****/ $_SESSION = array(); /***删除sessin id.由于session默认是基于cookie的,所以使用setcookie删除包含session id的cookie.***/ if (isset($_COOKIE[session_name()])) { setcookie(session_name(), '', time()-42000, '/'); }// 最后彻底销毁session. session_destroy(); 

一定要注意,不要使用unset($_SESSION)删除整个$_SESSION数组,这样将不能再通过$_SESSION超全局数组注册变量了。但如果想把某个用户在Session中注册的所有变量都删除,可以直接将数组变量$_SESSION赋上一个空数组。如下所示:

由此我们可以得出删除Session的步骤:

$_SESSION=array()

session_start() $_SESSION=array()/unset($_SESSION[‘xxx’])
session_destroy()

PHP默认的Session是基于Cookie的,Session
ID被服务器存储在客户端的Cookie中,所以在注销Session时也需要清除Cookie中保存的Session
ID,而这就必须借助setCookie()函数完成。在PHP脚本中,可以通过调用session_name()函数获取Session名称。删除保存在客户端Cookie中的Session
ID,代码如下所示:

解决PHP Session不过期以及SessionId保持不变的问题

//判断Cookie中是否存在session ID

session 回收机制:PHP采用Garbage Collection
process对过期session进行回收,然而并不是每次session建立时,都能够唤起
‘garbage collection’ process
,gc是按照一定概率启动的。这主要是出于对服务器性能方面的考虑,每个session都触发gc,浏览量大的话,服务器吃不消,然而按照一定概率开启gc,当流览量大的时候,session过期机制能够正常运行,而且服务器效率得到节省。细节应该都是多年的经验积累得出的。三个与PHP
session过期相关的参数(php.ini中):

if(isset($_COOKIE[session_name()])){

session.gc_probability = 1 session.gc_divisor = 1000
session.gc_maxlifetime = 1440

//删除包含Session
ID的cookie,注意第四个参数一定要和php.ini设置的路径相同

gc启动概率 = gc_probability / gc_divisor = 0.1%session过期时间
gc_maxlifetime
单位:秒当web服务正式提供时,session过期概率就需要根据web服务的浏览量和服务器的性能来综合考虑session过期概率。为每个session都开启gc,显然是不明智的,感觉有点“碰运气”的感觉,要是访问量小命中几率就小。我在本机测试过程中,几乎都没有被命中过,sessionid几天都不变,哪怕机器重启。测试过程中,这个过期概率值要设置大一点命中几率才高点。通过修改php配置文件的过期概率值,可以“碰运气”式的设置session过期,那有没有更好的办法呢?

setcookie(session_name(),”,time()-3600,’/’);

下面写的这个session类可以彻底解决session不过期以及sessionid不变的问题。

}

php /** * 扩展Session类(简单封装) * * @author slimboy * */class Session { /** * 初始化 */ static function _init(){ ini_set('session.auto_start', 0); //Session::start(); } /** * 启动Session */ static function start() { session_start(); } /** * 设置Session * * @param $name Session名称 * @param $value 值 * @param $time 超时时间(秒) */ public static function set($name,$value,$time){ if(empty($time)){ $time = 1800; //默认值 } $_SESSION[$name] = $value; $_SESSION[$name.'_Expires'] = time() + $time; } /** * 获取Session值 * * @param $name Session名称 */ public static function get($name){ //检查Session是否已过期 if(isset($_SESSION[$name.'_Expires']) && $_SESSION[$name.'_E xpires']time()){ return $_SESSION[$name]; }else{ Session::clear($name); return null; } } /** * 设置Session Domain * * @param $sessionDomain 域 * @return string */ static function setDomain($sessionDomain = null) { $return = ini_get('session.cookie_domain'); if(!empty($sessionDomain)) { ini_set('session.cookie_domain', $sessionDomain);//跨 域访问Session } return $return; } /** * 清除某一Session值 * * @param $name Session名称 */ static function clear($name){ unset($_SESSION[$name]); unset($_SESSION[$name.'_Expires']); } /** * 重置销毁Session */ static function destroy(){ unset($_SESSION); session_destroy(); } /** * 获取或设置Session id */ static function sessionid($id=null){ return session_id($id); } }简单调用: php //设置session Session::set('UserId', $userid, 3600); //读取session $userId = Session::get('UserId');

?>

通过前面的介绍可以总结出,Session的注销过程共需要4个步骤。在下例中,提供完整的四个步骤代码,运行该脚本就可以关闭Session,并销毁与本次会话有关的所有资源。代码如下所示:

//第一步:开启Session并初始化

session_start();

//第二步:删除所有Session的变量,也可以用unset($_SESSION[XXX])逐个删除

$_SESSION = array();

//第三步:如果使用基于Cookie的session,使用setCookie()删除包含Session
ID的cookie

if(isset($_COOKIE[session_name()])) {

setCookie(session_name(), “”, time()-42000, “/”);

}

//第四步:最后彻底销毁session

session_destroy();

?>

session的phpini配置选项

php.ini文件和Session有关的几个常用配置选项:

session.auto_start = 0 ; 在请求启动时初始化session

session.cache_expire = 180 ; 设置缓存中的会话文档在 n 分钟后过时

session.cookie_lifetime = 0 ;
设置按秒记的cookie的保存时间,相当于设置Session的过期时间,为0时表示直到浏览器被重启

session.auto_start=1,这样就无需每次使用session之前都要调用session_start()不建议使用.但启用该选项也有一些限制,如果确实启用了

session.auto_start,则不能将对象放入会话中,因为类定义必须在启动会话之前加载以在会话中重建对象。

session.cookie_path = / ; cookie的有效路径

session.cookie_domain = ; cookie的有效域

session.name = PHPSESSID; 用在cookie里的session的名字

session.save_handler = files ; 用于保存/取回数据的控制方式

session.save_path = /tmp ; 在 save_handler
设为文件时传给控制器的参数, 这是数据文件将保存的路径.

session.use_cookies = 1 ; 是否使用cookies

Session的垃圾自动回收机制

可以通过session_destroy()函数在页面中提供一个“退出”按钮,通过单击销毁本次会话。但如果用户没有单击退出按钮,而是直接关闭浏览器,或断网等情况,在服务器端保存的Session文件是不会删除的。虽然关闭浏览器,下次需要重新分配一个新的Session
ID重新登录,但这只是因为在php.ini中的设置seesion.cookie_lifetime=0,来设定Session
ID在客户端Cookie中的有效限期,以秒为单位指定了发送到浏览器的Cookie的生命周期。当系统赋予Session有效期限后不管浏览器是否开启,Session
ID都会自动消失。而客户端Session
ID消失服务器端保存的Session文件并没有被删除。所以没有被Sessoin
ID引用的服务器端Session文件,就成为了“垃圾”。

服务器保存的Session文件就是一个普通文本文件,所以都会有文件修改时间。“垃圾回收程序”启动后就是根据Session文件的修改时间,将所有过期的Session文件全部删除。通过在php.ini中设置session.gc_maxlifetime选项来指定一个时间(单位:秒),例如设置该选项值为1440(24分钟)。“垃圾回收程序”就会在所有Session文件中排查,如果有修改时间距离当前系统时间大于1440秒的就将其删除。

“session垃圾回收程序”是怎样的启动机制呢?“垃圾回收程序”是在调用session_start()函数时启动的。而一个网站有多个脚本,没有脚本又都要使用session_start()函数开启会话,又会有很多个用户同时访问,这就很可能session_start()函数在1秒内被调用N次,而如果每次都会启动“session垃圾回收程序”,这样是很不合理的。可以通过php.ini文件中修改“session.gc_probability和session.gc_divisor”两个选项,设置启动垃圾回收程序的概率。会根据“session.gc_probability/session.gc_divisor”公示计算概率,例如选项session.gc_probability=1,而选项session.gc_divisor=100,这样的概率就是“1/100”,即session_start()函数被调用100次才会有一次可能启动“垃圾回收程序”。

php.ini中相关的配置

session.cookie_lifetime=0;     关闭浏览器相应的cookie文件即被删除

session.gc_maxlifetime;    设置过期session时间,默认1440秒(24分钟)

session.gc_probability/session.gc_divisor;    
启动垃圾回收机制的概率(建议值为1/1000——5000)

cookie禁用时通过URL传递session的ID

使用Session跟踪一个用户,是通过在各个页面之间传递唯一的Session
ID,并通过Session
ID提取这个用户在服务器中保存的Session变量。常见的Session
ID传送方法有以下两种。

第一种方法是基于cookie的方式传递session ID,这种方式更优,但不总是可用,
因为用户在客户端可以屏蔽cokie;

第二种方法是通过url参数进行传递,直接将session ID嵌入到URL中去。

在Session的实现中通常都是采用Cookie的方式,客户端保存的Session
ID就是一个Cookie。当客户禁用Cookie时,Session
ID就不能在Cookie中保存,也就不能在页面之间传递,此时Session失效。不过PHP5在Linux平台可以自动检查Cookie状态,如果客户端禁用它,则系统自动把Session
ID附加到URL上传送。而使用Windows系统作为Web服务器则无此功能。

在PHP中提出了跟踪Session的另一种机制,如果客户浏览器不支持Cookie,则PHP可以重写客户请求的URL,把Session

ID添加到URL信息中。可以手动地在每个超链接的URL中都加上一个Session
ID,但工作量比较大,不建议使用这种方法。如下所示:

//开启session

session_start();

//在每个URL后面附加上参数,变量名为session_name()获取名称,值通过session_id()获取

echo ‘链接演示’;

?>

在使用Linux系统做服务器时,则在编辑PHP时如果使用了–enable-trans-sid配置选项,和运行时选项session.use_trans_sid都被激活,在客户端禁用Cookie时,相对URL将被自动修改为包含会话ID。如果没有这么配置,或者使用Windows系统作为服务器时,可以使用常量SID。该常量在会话启动时被定义,如果客户端没有发送适当的会话Cookie,则SID的格式为session_name=session_id,否则就为一个空字符串。因此可以无条件地将其嵌入到URL中去。在下例中使用两个脚本程序,演示了Session
ID的传送方法。

session_start();

$_SESSION[“username”]=”admin”;

echo “session ID:”.session_id().”;

?>

通过URL传递Session ID

在脚本test2.php中,输出test1.php脚本在Session变量中保存的另一个用户名。又在该页面中输出一次Session
ID,通过对比判断两个脚本是否使用同一个Session
ID。另外,在开启或关闭Cookie时,注意浏览器地址栏中URL的变化。代码如下所示:

session_start();

echo $_SESSION[“username”].”< br>”;

echo “session ID:”.session_id().”

“;

?>

You can leave a response, or trackback from your own site.

Leave a Reply

网站地图xml地图