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 12 PHP
PHP文件读写操作之文件读取方法详解
Jan 13 PHP
PHP如何解决网站大流量与高并发的问题
Jun 25 PHP
PHP提取字符串中的图片地址[正则表达式]
Nov 12 PHP
网页上facebook分享功能具体实现
Jan 26 PHP
destoon之一键登录设置
Jun 21 PHP
twig模板常用语句实例小结
Feb 04 PHP
万能的php分页类
Jul 06 PHP
php mysql PDO 查询操作的实例详解
Sep 23 PHP
PHP设计模式之简单工厂和工厂模式实例分析
Mar 25 PHP
php实现获取近几日、月时间示例
Jul 06 PHP
laravel 解决Validator使用中出现的问题
Oct 25 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写出自己的BLOG系统 2
2010/04/12 PHP
php启用sphinx全文搜索的实现方法
2014/12/24 PHP
ThinkPHP模板Volist标签嵌套循环输出多维数组的方法
2016/03/23 PHP
PHP云打印类完整示例
2016/10/15 PHP
PHP+iframe图片上传实现即时刷新效果
2016/11/18 PHP
php技巧小结【推荐】
2017/01/19 PHP
laravel使用Faker数据填充的实现方法
2019/04/12 PHP
通过ifame指向的页面高度调整iframe的高度
2006/10/05 Javascript
javascript第一课
2007/02/27 Javascript
JS中引用百度地图并将百度地图的logo和信息去掉
2013/09/29 Javascript
JS window对象的top、parent、opener含义介绍
2013/12/03 Javascript
完美兼容各大浏览器的jQuery插件实现图片切换特效
2014/12/12 Javascript
15款jQuery分布引导插件分享
2015/02/04 Javascript
JS创建对象的写法示例
2016/11/04 Javascript
Mongoose实现虚拟字段查询的方法详解
2017/08/15 Javascript
基于JS实现html中placeholder属性提示文字效果示例
2018/04/19 Javascript
解决Vue @submit 提交后不刷新页面问题
2020/07/18 Javascript
在Python中使用pngquant压缩png图片的教程
2015/04/09 Python
Python中用于转换字母为小写的lower()方法使用简介
2015/05/19 Python
Python新手入门最容易犯的错误总结
2017/04/24 Python
python使用scrapy发送post请求的坑
2018/09/04 Python
Python读取xlsx文件的实现方法
2019/07/04 Python
Python图像处理模块ndimage用法实例分析
2019/09/05 Python
python hash每次调用结果不同的原因
2019/11/21 Python
Python实现树莓派摄像头持续录像并传送到主机的步骤
2020/11/30 Python
HTML5 script元素async、defer异步加载使用介绍
2013/08/23 HTML / CSS
Java servlet面试题
2012/03/04 面试题
大学生求职自我评价
2014/01/16 职场文书
学校领导班子对照检查材料
2014/08/28 职场文书
2014年文艺部工作总结
2014/11/17 职场文书
2015年信贷员工作总结
2015/04/28 职场文书
2016年读书月活动总结范文
2016/04/06 职场文书
高中班主任寄语
2019/06/21 职场文书
python 中yaml文件用法大全
2021/07/04 Python
TypeScript中条件类型精读与实践记录
2021/10/05 Javascript
浅谈Vue的computed计算属性
2022/03/21 Vue.js