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 相关文章推荐
用Zend Encode编写开发PHP程序
Oct 09 PHP
一个域名查询的程序
Oct 09 PHP
PHP 面向对象实现代码
Nov 11 PHP
PHP开发中四种查询返回结果分析
Jan 02 PHP
PHP中的output_buffering详细介绍
Sep 27 PHP
thinkphp配置连接数据库技巧
Dec 02 PHP
php获取本周开始日期和结束日期的方法
Mar 09 PHP
php实现编辑和保存文件的方法
Jul 20 PHP
使用php实现从身份证中提取生日
May 09 PHP
由php中字符offset特征造成的绕过漏洞详解
Jul 07 PHP
PHP析构函数destruct与垃圾回收机制的讲解
Mar 22 PHP
Yii框架布局文件的动态切换操作示例
Nov 11 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之Memcache学习笔记
2013/06/17 PHP
php有道翻译api调用方法实例
2014/12/22 PHP
PHP获取指定月份第一天和最后一天的方法
2015/07/18 PHP
PHP数组游标实现对数组的各种操作详解
2016/01/26 PHP
Laravel路由设定和子路由设定实例分析
2016/03/30 PHP
PHP针对伪静态的注入总结【附asp与Python相关代码】
2017/08/01 PHP
php两点地理坐标距离的计算方法
2018/12/29 PHP
prototype Element学习笔记(篇二)
2008/10/26 Javascript
js实现单一html页面两套css切换代码
2013/04/11 Javascript
jQuery异步加载数据并添加事件示例
2014/08/24 Javascript
深入浅析JS Function()构造函数
2016/08/22 Javascript
JS 动态判断PC和手机浏览器实现代码
2016/09/21 Javascript
js实现数组去重方法及效率?Ρ? target=
2017/02/14 Javascript
微信小程序 数据遍历的实现
2017/04/05 Javascript
Node.js利用debug模块打印出调试日志的方法
2017/04/25 Javascript
深入理解nodejs中Express的中间件
2017/05/19 NodeJs
详解Angular-cli生成组件修改css成less或sass的实例
2017/07/27 Javascript
Angular中封装fancyBox(图片预览)遇到问题小结
2017/09/01 Javascript
详解react native页面间传递数据的几种方式
2018/11/07 Javascript
图文详解vue框架安装步骤
2019/02/12 Javascript
使用jquery的cookie实现登录页记住用户名和密码的方法
2019/03/13 jQuery
layui table 表格上添加日期控件的两种方法
2019/09/28 Javascript
Vue实现开心消消乐游戏算法
2019/10/22 Javascript
uni-app如何实现增量更新功能
2020/01/03 Javascript
JS实现多功能计算器
2020/10/28 Javascript
python装饰器实现对异常代码出现进行自动监控的实现方法
2020/09/15 Python
创业计划书如何编写
2014/02/06 职场文书
《手指教学》反思
2014/02/14 职场文书
暑期社会实践先进个人主要事迹
2014/05/22 职场文书
公司领导班子四风对照检查材料
2014/09/27 职场文书
家长高考寄语
2015/02/27 职场文书
保研推荐信格式
2015/03/25 职场文书
毕业生捐书活动倡议书
2015/04/27 职场文书
2015年妇委会工作总结
2015/05/22 职场文书
呼啸山庄读书笔记
2015/06/29 职场文书
PyCharm 配置SSH和SFTP连接远程服务器
2022/05/11 Python