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


Posted in PHP onAugust 18, 2015

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

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

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)…………

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

警告: 有些类型的数据不能被序列化因此也就不能保存在会话中。包括 resource 变量或者有循环引用的对象(即某对象将一个指向自己的引用传递给另一个对象)。

注册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代替之。例如:

    Page1.php

<?php
  Session_start(); //使用SESSION前必须调用该函数。

  $_SESSION[‘name']=”我是黑旋风李逵!”; //注册一个SESSION变量

  $_SESSION[‘passwd']=”mynameislikui”;
  $_SESSION[‘time']=time();
  echo '
  通过COOKIE传递SESSION'; //如果客户端支持cookie,可通过该链接传递session到下一页。

  echo '
  . SID . '">通过URL传递SESSION';//客户端不支持cookie时,使用该办法传递session.

  ?>

    Page2.php

<?php
  session_start();
  echo $_SESSION['name']; //

  echo $_SESSION['passwd']; //

  echo date('Y m d H:i:s', $_SESSION['time']);
  echo '
  返回山一页';
  ?>

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

  1. cookie
  2. URL 参数

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

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

session_id
session_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是否存在?
在以往的php版本中通常使用session_is_register()检查session是否存在,如果您使用$_SESSION[‘XXX']=XXX来注册会话变量,则session_is_register()函数不再起作用。你可以使用
isset($_SESSION[‘xxx'])来替代。

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

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

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

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

下面是PHP官方关于删除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();
  ?>

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

  1. session_start()
  2. $_SESSION=array()/unset($_SESSION['xxx'])
  3. session_destroy()

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

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

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

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

下面写的这个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');
?>
PHP 相关文章推荐
PHP集成FCK的函数代码
Sep 27 PHP
PHP Session变量不能传送到下一页的解决方法
Nov 27 PHP
php中将字符串转为HTML的实体引用的一个类
Feb 03 PHP
php采用curl访问域名返回405 method not allowed提示的解决方法
Jun 26 PHP
可以保证单词完整性的PHP英文字符串截取代码分享
Jul 15 PHP
php正则表达式获取内容所有链接
Jul 24 PHP
WordPress迁移时一些常见问题的解决方法整理
Nov 24 PHP
浅谈PHP拦截器之__set()与__get()的理解与使用方法
Oct 18 PHP
php strftime函数获取日期时间(switch用法)
May 16 PHP
ThinkPHP5.0框架结合Swoole开发实现WebSocket在线聊天案例详解
Apr 02 PHP
php 使用expat方式解析xml文件操作示例
Nov 26 PHP
PHP 实现缩略图
Mar 09 PHP
php微信公众平台开发之获取用户基本信息
Aug 17 #PHP
PHP添加图片水印、压缩、剪切的封装类
Aug 17 #PHP
php中switch语句用法详解
Aug 17 #PHP
Linux系统下PHP-FPM的安装和配置教程
Aug 17 #PHP
PHP连接Nginx服务器并解析Nginx日志的方法
Aug 16 #PHP
ThinkPHP开发框架函数详解:C方法
Aug 14 #PHP
提高php编程效率技巧
Aug 13 #PHP
You might like
2.PHP入门
2006/10/09 PHP
PHP禁止个别IP访问网站
2013/10/30 PHP
浅谈php正则表达式中的非贪婪模式匹配的使用
2014/11/25 PHP
WordPress迁移时一些常见问题的解决方法整理
2015/11/24 PHP
WHOOPS PHP调试库的使用
2017/09/29 PHP
thinkPHP3.2.3结合Laypage实现的分页功能示例
2018/05/28 PHP
用JQuery调用Session的实现代码
2010/10/29 Javascript
通过Javascript将数据导出到外部Excel文档的函数代码
2012/06/15 Javascript
JQuery入门—JQuery程序的代码风格详细介绍
2013/01/03 Javascript
基于jQuery.Validate验证库知识点的详解
2013/04/26 Javascript
js给页面加style无效果的解决方法
2014/01/20 Javascript
深入理解JS中的变量及作用域、undefined与null
2014/03/04 Javascript
jquery实现相册一下滑动两次的方法
2015/02/09 Javascript
JavaScript中的Number数字类型学习笔记
2016/05/26 Javascript
vue调用高德地图实例代码
2017/04/28 Javascript
JS高级技巧(简洁版)
2018/07/29 Javascript
JavaScript实现邮箱后缀提示功能的示例代码
2018/12/13 Javascript
vue App.vue中的公共组件改变值触发其他组件或.vue页面监听
2019/05/31 Javascript
Vue + Node.js + MongoDB图片上传组件实现图片预览和删除功能详解
2020/04/29 Javascript
vue在响应头response中获取自定义headers操作
2020/07/24 Javascript
arcgis.js控制地图地体的显示范围超出区域自动弹回(实现思路)
2021/01/28 Javascript
python连接mysql调用存储过程示例
2014/03/05 Python
python解析中国天气网的天气数据
2014/03/21 Python
Python urllib、urllib2、httplib抓取网页代码实例
2015/05/09 Python
Python中文字符串截取问题
2015/06/15 Python
在CentOS上配置Nginx+Gunicorn+Python+Flask环境的教程
2016/06/07 Python
pyqt 实现在Widgets中显示图片和文字的方法
2019/06/13 Python
python使用协程实现并发操作的方法详解
2019/12/27 Python
Django 返回json数据的实现示例
2020/03/05 Python
程序设计HTML5 Canvas API
2013/04/08 HTML / CSS
英国汽车零件购物网站:GSF Car Parts
2019/05/23 全球购物
印尼购物网站:iLOTTE
2019/10/16 全球购物
请写出 float x 与"零值"比较的 if 语句
2016/01/04 面试题
护理专科自荐书范文
2014/02/18 职场文书
新郎新娘致辞
2015/07/31 职场文书
MySQL 那些常见的错误设计规范,你都知道吗
2021/07/16 MySQL