php中实现精确设置session过期时间的方法


Posted in PHP onJuly 17, 2014

大多数据情况下我们对于session过期时间使用的是默认设置的时间,而对于一些有特殊要求的情况下我们可以设置一下session过期时间。

对此,可以在PHP中,设置php.ini,找到session.gc_maxlifetime = 1440 #(PHP5默认24分钟)
这里你可以随便设置一下过期时间.但是有人说设置以后,好象不起作用!
其实不是不起作用,而是因为系统默认:

session.gc_probability = 1
session.gc_divisor = 1000

garbage collection 有个概率的,1/1000就是session 1000次才有一次被回收。
只要你的访问量大了,那就能达到回收的效果.
或者你也可以设置一下session.gc_divisor 的值,
比如:session.gc_divisor = 1,这样就能明显的看到SESSION过期的效果了.

我们最常用的是在php程序中设置,如下例程序所示:

<?php
if(!isset($_SESSION['last_access'])||(time()-$_SESSION['last_access'])>60)
$_SESSION['last_access'] = time();
?>

这样就搞定了,如果要设置已过期的话也可以在程序中实现:

<?php
unset($_SESSION['last_access']);// 或 $_SESSION['last_access']='';
?>

session有过期的机制:

session.gc_maxlifetime 原来session 过期是一个小概率的事件,分别使用session.gc_probability和session.gc_divisor 来确定运行session 中gc 的概率 session.gc_probability和session.gc_divisor的默认值分别为 1和100。分别为分子和分母 所以session中gc的概率运行机会为1% 。如果修改这两个值,则会降低php的效率。所以这种方法是不对的!!
因此,修改php.ini文件中的gc_maxlifetime变量就可以延长session的过期时间了:(例如,我们把过期时间修改为86400秒)
session.gc_maxlifetime = 86400
然后,重启你的web服务(一般是apache)就可以了。

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

PHP中的session永不过期

不修改程序是最好的方法了,因为如果修改程序,测试部一定非常郁闷,那么只能修改系统环境配置,其实很 简单,打开php.ini设置文件,修改三行如下:

1、session.use_cookies

把这个的值设置为1,利用cookie来传递sessionid

2、session.cookie_lifetime

这个代表SessionID在客户端Cookie储存的时间,默认是0,代表浏览器一关闭SessionID就作废……就是因为这个所以PHP的 session不能永久使用! 那么我们把它设置为一个我们认为很大的数字吧,999999999怎么样,可以的!就这样。

3、session.gc_maxlifetime

这个是Session数据在服务器端储存的时间,如果超过这个时间,那么Session数据就自动删除! 那么我们也把它设置为99999999。

就这样一切ok了,当然你不相信的话就测试一下看看——设置一个session值过个10天半个月的回来看看,如果你的电脑没有断电或者宕机,你仍然可以看见这个sessionid。

当然也可能你没有控制服务器的权限并不能像我一样幸运的可以修改php.ini设置,一切依靠我们自己也是有办法的,当然就必须利用到客户端存储 cookie了,把得到的sessionID存储到客户端的cookie里面,设置这个cookie的值,然后把这个值传递给session_id()这 个函数,具体做法如下:

<?php
session_start(); // 启动Session 
$_SESSION['count']; // 注册Session变量Count 
isset($PHPSESSID)?session_id($PHPSESSID):$PHPSESSID = session_id(); 
// 如果设置了$PHPSESSID,就将SessionID赋值为$PHPSESSID,否则生成SessionID 
$_SESSION['count']++; // 变量count加1 
setcookie('PHPSESSID', $PHPSESSID, time()+3156000); // 储存SessionID到Cookie中 
echo $count; // 显示Session变量count的值 
?>

session失效不传递

我们先写个php文件:<?=phpinfo()?>, 传到服务器去看看服务器的参数配置。
转到session部分,看到session.use_trans_sid参数被设为了零。
这个参数指定了是否启用透明SID支持,即session是否随着URL传递。我个人的理解是,一旦这个参数被设为0,那么每个URL都会启一个session。这样后面页面就无法追踪得到前面一个页面的session,也就是我们所说的无法传递。两个页面在服务器端生成了两个session文件,且无关联。(此处精确原理有待确认)
所以一个办法是在配置文件php.ini里把session.use_trans_sid的值改成1。

当然我们知道,不是谁都有权限去改php的配置的,那么还有什么间接的解决办法呢?
下面就用两个实例来说明:
文件1 test1.php

<?php
//表明是使用用户ID为标识的session
session_id(SID);
//启动session
session_start();
//将session的name赋值为Havi
$_SESSION['name']="Havi";
//输出session,并设置超链接到第二页test2.php
echo "<a href="test2.php" rel="external nofollow" >".$_SESSION['name']."</a>";
?>

文件2: test2.php

<?php
表明是使用用户ID为标识的session
session_id(SID);
//启动session
session_start();
//输出test1.php中传递的session。
echo "This is ".$_SESSION['name'];
?>

所以,重点是在session_start();前加上session_id(SID);,这样页面转换时,服务器使用的是用户保存在服务器session文件夹里的session,解决了传递的问题。
不过有朋友会反映说,这样一来,多个用户的session写在一个SID里了,那Session的价值就发挥不出来了。所以还有一招来解决此问题,不用加session_id(SID);前提是你对服务器的php.ini有配置的权限:
output_buffering改成ON,道理就不表了。
第二个可能的原因是对服务器保存session的文件夹没有读取的权限,还是回到phpinfo.php中,查看session保存的地址:

session.save_path: var/tmp

所以就是检查下var/tmp文件夹是否可写。
写一个文件:test3.php来测试一下:

<?php
echo var_dump(is_writeable(ini_get("session.save_path")));
?>

如果返回bool(false),证明文件夹写权限被限制了,那就换个文件夹咯,在你编写的网页里加入:

//设置当前目录下session子文件夹为session保存路径。
$sessSavePath = dirname(__FILE__).'/session/';
//如果新路径可读可写(可通过FTP上变更文件夹属性为777实现),则让该路径生效。
if(is_writeable($sessSavePath) && is_readable($sessSavePath))
{
session_save_path($sessSavePath);
}
PHP 相关文章推荐
PHP动态图像的创建
Oct 09 PHP
回答PHPCHINA上的几个问题:URL映射
Feb 14 PHP
php面向对象全攻略 (十二) 抽象方法和抽象类
Sep 30 PHP
windows下PHP_intl.dll正确配置方法(apache2.2+php5.3.5)
Jan 14 PHP
php使用百度翻译api示例分享
Jan 31 PHP
PHP MSSQL 分页实例
Apr 13 PHP
PHP多维数组排序array详解
Nov 21 PHP
PHP简单实现正则匹配省市区的方法
Apr 13 PHP
PHP+ajax实现获取新闻数据简单示例
May 08 PHP
php 可变函数使用小结
Jun 12 PHP
PHP 7.4中使用预加载的方法详解
Jul 08 PHP
php优化查询foreach代码实例讲解
Mar 24 PHP
ThinkPHP跳转页success及error模板实例教程
Jul 17 #PHP
浅谈php安全性需要注意的几点事项
Jul 17 #PHP
PHP采用XML-RPC构造Web Service实例教程
Jul 16 #PHP
ThinkPHP应用模式扩展详解
Jul 16 #PHP
CodeIgniter模板引擎使用实例
Jul 15 #PHP
PHP以mysqli方式连接类完整代码实例
Jul 15 #PHP
destoon实现底部添加你是第几位访问者的方法
Jul 15 #PHP
You might like
用PHP实现WEB动态网页静态
2006/10/09 PHP
PHP5与MySQL数据库操作常用代码 收集
2010/03/21 PHP
解析PHP中DIRECTORY_SEPARATOR,PATH_SEPARATOR两个常量的作用
2013/06/21 PHP
PHP之将POST数据转化为字符串的实现代码
2016/11/03 PHP
laravel中的一些简单实用功能
2018/11/03 PHP
addEventListener()第三个参数useCapture (Boolean)详细解析
2013/11/07 Javascript
怎么判断js脚本加载完成
2014/02/28 Javascript
js实现图片和链接文字同步切换特效的方法
2015/02/20 Javascript
jQuery实现切换字体大小的方法
2015/03/10 Javascript
Javascript实现飞动广告效果的方法
2015/05/25 Javascript
JavaScript Ajax编程 应用篇
2016/07/02 Javascript
js获取文件里面的所有文件名(实例)
2017/10/17 Javascript
Node.js搭建小程序后台服务
2018/01/03 Javascript
AjaxUpLoad.js实现文件上传
2018/03/05 Javascript
深入理解移动前端开发之viewport
2018/10/19 Javascript
JavaScript模板引擎原理与用法详解
2018/12/24 Javascript
Vue 实现手动刷新组件的方法
2019/02/19 Javascript
node.js基于dgram数据报模块创建UDP服务器和客户端操作示例
2020/02/12 Javascript
Python端口扫描简单程序
2016/11/10 Python
python同时遍历数组的索引和值的实例
2018/11/15 Python
解决python ogr shp字段写入中文乱码的问题
2018/12/31 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
2019/05/15 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
浅谈matplotlib 绘制梯度下降求解过程
2020/07/12 Python
关于css中margin的值和垂直外边距重叠问题
2020/10/27 HTML / CSS
中国旅游网站:同程旅游
2016/09/11 全球购物
艺术爱好者的自我评价分享
2013/10/08 职场文书
学生实习自我鉴定
2013/10/11 职场文书
销售提升方案
2014/06/07 职场文书
环保志愿者活动总结
2014/06/27 职场文书
装修施工安全责任书
2014/07/24 职场文书
大连星海广场导游词
2015/02/10 职场文书
师德师风主题教育活动总结
2015/05/07 职场文书
2015年超市工作总结范文
2015/05/26 职场文书
如何开发一个渐进式Web应用程序PWA
2021/05/10 Javascript
python 如何在list中找Topk的数值和索引
2021/05/20 Python