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 相关文章推荐
phpize的深入理解
Jun 03 PHP
php获取数组中重复数据的两种方法
Jun 28 PHP
PHP+Memcache实现wordpress访问总数统计(非插件)
Jul 04 PHP
Thinkphp搜索时首页分页和搜索页保持条件分页的方法
Dec 05 PHP
php中的动态调用实例分析
Jan 07 PHP
php函数实现判断是否移动端访问
Mar 03 PHP
PHP实现的memcache环形队列类实例
Jul 28 PHP
php打包网站并在线压缩为zip
Feb 13 PHP
php实现按天数、星期、月份查询的搜索框
May 02 PHP
PHP编程中的Session阻塞问题与解决方法分析
Aug 07 PHP
PHP7扩展开发之基于函数方式使用lib库的方法详解
Jan 15 PHP
php实现 master-worker 守护多进程模式的实例代码
Jul 20 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
一个捕获函数输出的函数
2007/02/14 PHP
在字符串指定位置插入一段字符串的php代码
2010/02/16 PHP
编写可维护面向对象的JavaScript代码[翻译]
2011/02/12 Javascript
精通Javascript系列之数值计算
2011/06/07 Javascript
jQuery Animation实现CSS3动画示例介绍
2013/08/14 Javascript
让JavaScript的Alert弹出框失效的方法禁止弹出警告框
2014/09/03 Javascript
jQuery中:lt选择器用法实例
2014/12/29 Javascript
jQuery焦点控制图层展示延迟隐藏的方法
2015/03/09 Javascript
javascript相关事件的几个概念
2015/05/21 Javascript
Bootstrap组件之下拉菜单,多级菜单及按钮布局方法实例
2017/05/25 Javascript
使用layer弹窗和layui表单实现新增功能
2018/08/09 Javascript
如何在 JavaScript 中更好地利用数组
2018/09/27 Javascript
微信小程序拍照和摄像功能实现方法示例
2019/02/01 Javascript
分享一个vue项目“脚手架”项目的实现步骤
2019/05/26 Javascript
低版本中Python除法运算小技巧
2015/04/05 Python
深入分析python数据挖掘 Json结构分析
2018/04/21 Python
Python+Pyqt实现简单GUI电子时钟
2021/02/22 Python
django+echart数据动态显示的例子
2019/08/12 Python
Django中使用MySQL5.5的教程
2019/12/18 Python
Python3 Click模块的使用方法详解
2020/02/12 Python
Python基于opencv的简单图像轮廓形状识别(全网最简单最少代码)
2021/01/28 Python
css 如何让背景图片拉伸填充避免重复显示
2013/07/11 HTML / CSS
将一个文本文件的内容按倒序打印出来
2015/01/05 面试题
数控专业个人求职信范例
2013/11/29 职场文书
办公室助理岗位职责
2013/12/25 职场文书
全国道德模范事迹
2014/02/01 职场文书
20年同学聚会感言
2014/02/03 职场文书
2014信息公开实施方案
2014/02/22 职场文书
安全承诺书格式
2014/05/21 职场文书
2014年行政工作总结
2014/11/19 职场文书
走进毛泽东观后感
2015/06/04 职场文书
详解MySQL主从复制及读写分离
2021/05/07 MySQL
如何使用flask将模型部署为服务
2021/05/13 Python
Python实现socket库网络通信套接字
2021/06/04 Python
Python 发送SMTP邮件的简单教程
2021/06/24 Python
Nginx 反向代理解决跨域问题多种情况分析
2022/01/18 Servers