深入讲解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 相关文章推荐
Win9x/ME下Apache+PHP安装配置
Oct 09 PHP
discuz的php防止sql注入函数
Jan 17 PHP
php防止sql注入示例分析和几种常见攻击正则表达式
Jan 12 PHP
PHP调用MySQL存储过程并返回值的方法
Dec 26 PHP
PHP实现将浏览历史页面网址保存到cookie的方法
Jan 26 PHP
php将远程图片保存到本地服务器的实现代码
Aug 03 PHP
PHP错误机制知识汇总
Mar 24 PHP
深入理解php printf() 输出格式化的字符串
May 23 PHP
Laravel SQL语句记录方式(推荐)
May 26 PHP
学习PHP Cookie处理函数
Aug 09 PHP
php 判断IP为有效IP地址的方法
Jan 28 PHP
PHP支付宝当面付2.0代码
Dec 21 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
php adodb连接带密码access数据库实例,测试成功
2008/05/14 PHP
PHP中全面阻止SQL注入式攻击分析小结
2012/01/30 PHP
thinkphp多层MVC用法分析
2015/12/30 PHP
PHP实现四种基础排序算法的运行时间比较(推荐)
2016/08/11 PHP
PHP Post获取不到非表单数据的问题解决办法
2018/02/27 PHP
JS 动态获取节点代码innerHTML分析 [IE,FF]
2009/11/30 Javascript
js 屏蔽鼠标右键脚本附破解方法
2009/12/03 Javascript
jQuery插件开发全解析
2012/10/10 Javascript
jquery $(&quot;#variable&quot;) 循环改变variable的值示例
2014/02/23 Javascript
搭建pomelo 开发环境
2014/06/24 Javascript
Javascript正则控制文本框只能输入整数或浮点数
2014/09/02 Javascript
Javascript基础教程之变量
2015/01/18 Javascript
javascript基本语法
2016/05/31 Javascript
AngularJS ng-template寄宿方式用法分析
2016/11/07 Javascript
深入理解vue-loader如何使用
2017/06/06 Javascript
详解vue几种主动刷新的方法总结
2019/02/19 Javascript
JavaScript实现星级评价效果
2019/05/17 Javascript
微信小程序实现上传word、txt、Excel、PPT等文件功能
2019/05/23 Javascript
vue实现短信验证码输入框
2020/04/17 Javascript
[01:14]英雄,所敬略同——2018完美盛典宣传视频
2018/12/05 DOTA
python中使用%与.format格式化文本方法解析
2017/12/27 Python
Python简单实现控制电脑的方法
2018/01/22 Python
python使用turtle库绘制时钟
2020/03/25 Python
Python3内置模块random随机方法小结
2019/07/13 Python
Python对Tornado请求与响应的数据处理
2020/02/12 Python
详解python的xlwings库读写excel操作总结
2021/02/26 Python
波兰在线香水店:Perfumy.pl
2019/08/12 全球购物
Harman Audio官方商店:购买JBL、Harman Kardon、Infinity和AKG
2019/12/05 全球购物
Java servlet面试题
2012/03/04 面试题
创业计划书中包含的9个方面
2013/12/26 职场文书
教育英语专业毕业生的求职信
2014/03/13 职场文书
家长建议怎么写
2014/05/15 职场文书
博士生导师推荐信
2014/07/08 职场文书
党员个人批评与自我批评
2014/10/14 职场文书
毕业论文致谢格式模板
2015/05/14 职场文书
反邪教学习心得体会
2016/01/15 职场文书