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 cURL和Rolling cURL并发方式比较
Oct 30 PHP
discuz加密解密函数使用方法和中文注释
Jan 21 PHP
php实现telnet功能示例
Apr 08 PHP
ThinkPHP基本的增删查改操作实例教程
Aug 22 PHP
深入分析PHP引用(&amp;)
Sep 04 PHP
PHP获取文件行数的方法
Jun 10 PHP
使用PHP编写发红包程序
Jul 22 PHP
php实现的debug log日志操作类实例
Jul 12 PHP
PHP类和对象相关系统函数与运算符小结
Sep 28 PHP
总结一些PHP中好用但又容易忽略的小知识
Jun 02 PHP
购物车实现的几种方式优缺点对比
May 02 PHP
PHP应用跨时区功能的实现方法
Mar 21 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
简单采集了yahoo的一些数据
2007/02/14 PHP
Laravel 5框架学习之模型、控制器、视图基础流程
2015/04/08 PHP
ThinkPHP函数详解之M方法和R方法
2015/09/10 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
PHP工厂模式的日常使用
2019/03/20 PHP
Javascript typeof 用法
2008/12/28 Javascript
JavaScript 精粹读书笔记(1,2)
2010/02/07 Javascript
使用jQuery实现dropdownlist的联动效果(sharepoint 2007)
2011/03/30 Javascript
JS实现商品倒计时实现代码
2013/05/03 Javascript
javascript同页面多次调用弹出层具体实例代码
2013/08/16 Javascript
Array 重排序方法和操作方法的简单实例
2014/01/24 Javascript
Bootstrap每天必学之工具提示(Tooltip)插件
2016/04/26 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
2016/12/21 Javascript
原生Javascript插件开发实践
2017/01/18 Javascript
基于JavaScript实现选项卡效果
2017/07/21 Javascript
微信小程序实现时间预约功能
2018/11/27 Javascript
微信实现自动跳转到用其他浏览器打开指定APP下载
2019/02/15 Javascript
微信小程序:数据存储、传值、取值详解
2019/05/07 Javascript
微信小程序云开发之使用云函数
2019/05/17 Javascript
微信小程序实现禁止分享代码实例
2019/10/19 Javascript
JavaScript经典案例之简易计算器
2020/08/24 Javascript
[43:35]TI4 循环赛第二日Liquid vs Fnatic
2014/07/11 DOTA
[42:25]2018DOTA2亚洲邀请赛 4.5 淘汰赛 LGD vs Liquid 第三场
2018/04/06 DOTA
Python中使用dom模块生成XML文件示例
2015/04/05 Python
python 使用 requests 模块发送http请求 的方法
2018/12/09 Python
Python OrderedDict的使用案例解析
2019/10/25 Python
Flask中endpoint的理解(小结)
2019/12/11 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
python利用faker库批量生成测试数据
2020/10/15 Python
Python 中如何使用 virtualenv 管理虚拟环境
2021/01/21 Python
HTML5使用Audio标签实现歌词同步的效果
2016/03/17 HTML / CSS
Canvas globalCompositeOperation
2018/12/18 HTML / CSS
单身旅行者的单身假期:Just You
2018/04/08 全球购物
镇党委书记群众路线整改措施思想汇报
2014/10/13 职场文书
歌咏比赛口号大全
2015/12/25 职场文书
Python创建SQL数据库流程逐步讲解
2022/09/23 Python