高手路过不要错过:Session最难的两个问题?
1、session.cache_expire(),究竟有什么用?哪位能讲一下原理?
这涉及session的生命周期问题?
我试过,session.gc_maxlife应是设成为垃圾的时间!例,如果设为20分钟,且第次启动会话就清除垃圾,则时间一到会立即清除session文件,变量当然就没有了!
两者究竟有何区别?
2、基于cookie的session,设session 下cookie的存活期究竟有什么用?因为即使客户端有存活期,服务器端没有不行?所以须两端都有才行?
然而,只要每session_start(),就会产生新id并更改cookie,这意味着原来的cookie就没用了!
所以,session 和cookie给合使用可能是个伪命题!
如果各位高手有结合使用的例子,可以给指点一个代码!
事实的情况是,以下的情况可能是最有效率的:
如果客户要求下次不需录验证:就直接用cookie;不用session!
如果要求安全性高,不用cookie,直接用session!
上面也是一种结合使用!
不知各位高手认为如何?是否有更好的办法和思路!大家都发发言讨论一下!
问题点数:30、回复次数:28Top
1 楼MAD_FROG()回复于 2006-12-26 20:14:58 得分 1
session_cache_expire() returns the current setting of session.cache_expire. The value returned should be read in minutes, defaults to 180. If new_cache_expire is given, the current cache expire is replaced with new_cache_expire.
"只要每session_start(),就会产生新id并更改cookie,这意味着原来的cookie就没用了":
我不是什么高手,但是我觉得这正是用session 和cookie给合的原因,首先用cookie保存了信息在客户端,session过期了,但cookie还在,session可以利用cookie初始化一下,这样即使session过期时间设短一点也不影响,避免了session过期时间过长造成的服务器资源浪费.拙见,见笑了!Top
2 楼ShadowSniper(the future is ours)回复于 2006-12-26 21:31:49 得分 0
楼上的id应该是取自war3的那位天才UD选手疯狂青蛙Top
3 楼fxs_2008()回复于 2006-12-26 22:21:10 得分 0
你好!MAD_FROG() !
"只要每session_start(),就会产生新id并更改cookie,这意味着原来的cookie就没用了":
我不是什么高手,但是我觉得这正是用session 和cookie给合的原因,首先用cookie保存了信息在客户端,session过期了,但cookie还在,session可以利用cookie初始化一下,这样即使session过期时间设短一点也不影响,避免了session过期时间过长造成的服务器资源浪费.
——————————————————————————————————————————
您能否给段代码?简单的代码模型!给个思路!
我测 的代码模型如下:
1、session存数据库
2、登录成功后启动新会话:登录页:login.php
require("include/session_inc.php"); //设置session 数据库保存
session_start();
$_SESSION['name']=$username; //注册一个SESSION变量
$_SESSION['passwd']=$password;
$_SESSION['admin']='true';
$_SESSION['time']=time();
$lifetime=24*3600;
setcookie(session_name(),session_id(),time()+$lifetime,"/");
3、测试页:test.php
if (isset($_COOKIE['PHPSESSID'] ) && $_COOKIE['PHPSESSID'] !='' )
{
$sessionid=$_COOKIE['PHPSESSID'];
require("include/session_inc.php");
session_id($sessionid);
session_start();
if($_SESSION['admin']!='true')
{
echo session_id();
echo "cookied存在但session不正确";
echo "请重新登录";
}
else
{
echo session_id();
echo "成功取得原cookieID";
echo $_SESSION['name'];
echo $_SESSION['passwd'];
echo date('Y n j H i',$_SESSION['time']);
echo "成功验证";
}
}else
{
require("session_inc.php");
session_start();
if($_SESSION['admin']!='true')
{
echo session_id();
echo "cookie不存在,session也不存在";
echo "请重新登录";
}
else
{
echo session_id();
echo $_SESSION['name'];
echo "cookie和session都存在";
echo "成功验证";
}
}
大家看这个模型有没有什么问题?有没有更好的!
我测试结果是:
登录成功后正常,但下次不登录直接进测页就会出总题!我也不在道问题在什么地方?大家测一下看有什么问题!
Top
4 楼fxs_2008()回复于 2006-12-26 22:33:57 得分 0
你好!MAD_FROG() !
session可以利用cookie初始化一下!
你的意思是说,如果用户登录时要求保存一定时间,那登录成功后存cookie 时一定要存数组变量了,就是按正常使用cookie!
下次判断验证时从cookie取出数据变量,用这些变量初始化session!
能给个代码模型吗?Top
5 楼hnxxwyq(独自流浪)回复于 2006-12-27 08:40:33 得分 1
$sessionid=$_COOKIE['PHPSESSID'];
require("include/session_inc.php");
session_id($sessionid);
require("session_inc.php");
session_start();
你的这2个逻辑判断是不是有问题啊,上面通过判断cookie存储的session_id获取验证,那你下面呢?难道说没有获取cookie以后就新创建一个会话?那么下面的判断 if($_SESSION['admin']!='true')这个不就永远不会出现$_SESSION['admin']=='true'的情况!!
另外你说遇到错误,请指明具体错误,大家也好帮助你啊!Top
6 楼yueliangdao0608((深圳PHPER.MSN:yueliangdao0608@gmail.com)回复于 2006-12-27 09:26:31 得分 3
session_cache_expire
(PHP 4 >= 4.2.0, PHP 5)
session_cache_expire -- Return current cache expire
Description
int session_cache_expire ( [int new_cache_expire] )
session_cache_expire() returns the current setting of session.cache_expire. The value returned should be read in minutes, defaults to 180. If new_cache_expire is given, the current cache expire is replaced with new_cache_expire.
The cache expire is reset to the default value of 180 stored in session.cache_limiter at request startup time. Thus, you need to call session_cache_expire() for every request (and before session_start() is called).
例子 1. session_cache_expire() example
<?php
/* set the cache limiter to 'private' */
session_cache_limiter('private');
$cache_limiter = session_cache_limiter();
/* set the cache expire to 30 minutes */
session_cache_expire(30);
$cache_expire = session_cache_expire();
/* start the session */
session_start();
echo "The cache limiter is now set to $cache_limiter<br />";
echo "The cached session pages expire after $cache_expire minutes";
?>
Top
7 楼fxs_2008()回复于 2006-12-27 09:49:00 得分 0
回hnxxwyq(独自流浪):
我代码模型的思路是这样的:
1、如果验证成功。设cookie存活期。
2、测试页逻辑!
先测试cookie
如果存在cooKie,则取回ID,看session中有无相应变量(即$_session['admin']= true)。有则通过验证。没有重新登录。
如果不存在cookie,则看有没有session,(即$_session['admin']= true)。有的话说明验证过了。
问题在于,如果不登录而直接打开测页,cookie总是不存在。Top
8 楼ice_berg16(寻梦的稻草人)回复于 2006-12-27 11:07:26 得分 3
session通过cookie保存它的id,这个过程是自动的,不需要你手工操作,
默认这个cookie在浏览器关闭后自动失效,如果想保存cookie就设置session.cookie_lifetime长一些。
下面这个测试注释掉ini_set这一行和不注释掉效果是完全不同的。
先打开页面,刷新,然后关闭页面,再打开。看效果。
<?php
ini_set("session.cookie_lifetime", 60);
session_start();
print_r(session_get_cookie_params());
if(!isset($_SESSION['login'])){
echo '没登录';
$_SESSION['login'] = 1;
}
else{
echo '已登录';
}
?>Top
9 楼fxs_2008()回复于 2006-12-27 13:11:05 得分 0
楼上 ini_set("session.cookie_lifetime", 60);
这是否是指session ID 和cookie ID(两者是一个数)在60内均存在且有效。即使重新打开IE。
这应是设置所有cookie的默认生命周期。结果可能影响session的生命周期。可能是使session 和cookie生命周期同步吧(当session不被清理的情况下)
我还没测试。
但如:我手动设置cookie 生命周期,会改变默认设置。这种情况怎办?
Top
10 楼fxs_2008()回复于 2006-12-27 15:24:56 得分 0
回yueliangdao0608((深圳)PHP和MYSQLQQ:38257291)
上面我也先前看过。但不知道,这个缓存究竟是如保运作的?有什么作用?有应用实例吗?Top
11 楼fxs_2008()回复于 2006-12-28 15:03:35 得分 0
继续顶,期待大家讨论Top
12 楼Meteorlet(http://smartdict.cn)回复于 2006-12-28 18:31:46 得分 8
1. session的传递只有一个session id, 默认PHPSESSID=xxxxxxxx保存在cookie里,
因为cookie有lifetime,所以session.cookie_lifetime就是用来设置这个lifetime的。对服务器来说,第一次登录以后获得了PHPSESSID,以后服务器只认这个ID,如果客户端关闭了IE对服务器来说根本不可能知道IE关闭了,重新打开IE的时候,只要请求的页面里PHPSESSID是相同的,它就认为你是一直登录着的。而如何让IE关闭页面之后再请求页面还带有这个PHPSESSID就只需要设置cookie的lifetime,不管是设置session.cookie_lifetime还是代码中setcookie(session_name(), session_id(), time() + 3600)效果是一样的。
2. session.gc_maxlifetime是垃圾回收(Garbage Collection)时间,也就是说每一个用户登录都会生成session文件,如果用户中途关闭IE,那么服务器就会生成一个垃圾文件。gc_maxlifetime就是用来定时删除一些过期的垃圾文件的。
3. session.cache_expire()是设置页面缓存的,具体在HTTP协议里说的很清楚的,跟以上session变量没有什么关系。
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
4. 不要以为session就是cookie, cookie只不过是session id传递的一种方法,用form,url都可以实现session. cookie保存的仅仅是session id,不是说cookie不能保存数据,而是cookie保存数据不安全,session就是为了要解决这个问题,所以session id是一个散列字符串,在有效时间内是不能被人猜出来的。Top
13 楼fxs_2008()回复于 2006-12-28 22:29:18 得分 0
回:Meteorlet(www.dictworld.com)
多谢指点:
我觉你说得最明白,我觉你说的2、3、4点都是有道理的,也最为透彻。也解我不少疑惑。
但我的问题仍在第1点:
如果cookie只是存ID的情况下,我设session.cookie_lifetime,用(session_name(), session_id(), time() + 3600)
或session_set_cookie_params(),即设cookie存活期,这个服务器session无关。
如果session ID有存活期且未过期,且服务器端存在session的情况下(未被垃圾收集或人工注消),当关闭浏览器后下次打开浏览器时,如何用这个ID取得服务器端的session呢?
我的难题就在这?
我测试的情况是,只要session_start(),就会产生新的ID并覆盖原来的cookie,即使我这次成功取得了,下次cookie又变了,除非我每次取得后再手动重设cookie,这还得cookie过期计算时间,我没有试过!比较复杂!
大家有没有好的方法!
Top
14 楼fxs_2008()回复于 2006-12-30 12:52:34 得分 0
继续顶Top
15 楼ashchen(老陳)回复于 2006-12-30 13:50:43 得分 6
看来还得我来回答
session_set_cookie_params里的整数可不能用time()+....这种
楼主要想让客户端缓存session的cookie,这样客户端关掉浏览器10分钟后重启电脑回来还能用这个session,不用重新登录
这个问题在手册的留言里有讨论,其中session_set_cookie_params的整数参数是缓存服务器过后多少秒数,你要保留一天session,参数就是86400,而不是time()+86400
用httpwatch抓一下cookie就很容易理解了,session处理模块自动集成了setcookie的处理,当然还设置了其他http header
_______________________________
www.cosrc.com
caare.cosrc.comTop
16 楼Meteorlet(http://smartdict.cn)回复于 2006-12-30 14:00:50 得分 2
session_start()的工作原理是这样的:
1) 首先在cookie(如果配置成cookie传递Session ID的话)里找PHPSESSID=xxxxx
2)读取PHPSESSID的值,如果读不到就重新随机初始化一个ID
3)初始化超全局数组$_SESSION(这一步就是读取文件反序列化的过程)
所以如果成功写入cookie的话,那么关闭IE再打开,只要cookie里有这个ID,服务器都认为是一样的。
以下代码运行一次输出success,运行第二次输出login,关闭IE再打开还是显示login:
<?php
session_start();
setcookie(session_name(), session_id(), time() + 3600);
if (empty($_SESSION['login']))
{
$_SESSION['login'] = 1;
print("Success");
} else {
print("Login");
}
?>
而且session_start()之前的session id是可以自己初始化的,比如:
session_id($_COOKIE[session_name()]);
session_start();Top
17 楼ashchen(老陳)回复于 2006-12-30 14:03:12 得分 1
另外session_set_cookie_params必须写在session_star前面,否则不起作用
至于session_set_cookie_params会不会自动导致session数据过期加长还没看,估计会自动加长服务器端session数据的过期时间
原理是这样的,用户进来,服务器检查是否有cookie传递过来的session id,有就从服务器查找对应的id数据,没有就new一个,通过cookie发到客户端
这是默认状态,session id是浏览器进程cookie,关掉浏览器就没了,如果要保存登录,就用session_set_cookie_params来设置传递session id的cookie过期时间。
如果访问量较大,那么最好不要用这种方式,因为...服务器自动延长了session数据的过期时间,加长了服务器端检索session数据的时间&负载。
_______________________________
www.cosrc.com
care.cosrc.comTop
18 楼ashchen(老陳)回复于 2006-12-30 14:09:07 得分 1
假设:把session id的过期时间设成1年
那么服务器要把你的session数据保存1年,如果有一直有新ip来访问,oh my god
如同那歌唱的了:i will be right here waiting for you
但愿不是那么处理session数据的。
Top
19 楼fxs_2008()回复于 2006-12-30 23:08:31 得分 0
感谢楼上两位指点!又让我多学了东西!
我也一直测试,已有点眉目!
我原来的问题是这样的:
即使我设了session_set_cookie_params($time);这只是设置了客户端cookie的周期。实际上服务器session是不认这个的。他只认sessionID。
如果session.lifetime的默认生存周期为0,即INI里的那个。
意味着,只要session_start(),就会重写cookie,并且生存周期为0。因为session_name()重名。
所以,即使设cookie设置了生存期,只要遇session_start()就归零了!
解决的方法可能是样:
1、如果登录成功
session_start();
用这个sessionID,但不用默认的phpsessID变量名设cookie.
如:
setcookie("DPHP",session_id(),$lifetime,"/");
即用另一个变量但用同一ID存cookie及生存期。
2、验证
判 断
if (isset($_COOKIE['DPHP']) && $_COOKIE['DPHP']!='')
例如:
require("include/session_inc.php");
if (isset($_COOKIE['DPHP']) && $_COOKIE['DPHP']!='')
{
session_id($_COOKIE['DPHP']);
session_start();
if($_SESSION['admin']!='true')
{
echo "cookie存在但session不正确请得新登录";
}
else
{
/* $lifetime=mktime($_SESSION['cookietime'])-mktime();
if ($lifetime>0)
{
$lifetime=time()+$lifetime;
setcookie(session_name(),session_id(),$lifetime,"/");
*/
echo "cookie、session均正确,成功新登录";
}
}
else
{
session_start();
if($_SESSION['admin']='true')
{
echo "成功登录";
}
else
{
echo "请重新登录";
}
}
这样,只要$_COOKIE['DPHP']存在,就用这个ID取服务器端的SEssion.
$_COOKIE['PHPSESSID']只有浏览器生存期
而$_COOKIE['DPHP']生存期手设
两个都是同一ID。
这样就实现cookie和session的结合应用了,达到最佳效果!
我认为,cookie和session的生存期是不相关(只在浏览器不关闭时相关)。因此,要想取session,session生存期应>cookie生存期,由于session会大量存在,因此这种应用不宜超过两周!Top
20 楼fxs_2008()回复于 2006-12-30 23:09:51 得分 0
我正在测试,如果成功后再告知大家!Top
21 楼helloyou0(你好!)回复于 2006-12-31 11:24:10 得分 4
这样,只要$_COOKIE['DPHP']存在,就用这个ID取服务器端的SEssion.
$_COOKIE['PHPSESSID']只有浏览器生存期
而$_COOKIE['DPHP']生存期手设
两个都是同一ID。
这样就实现cookie和session的结合应用了,达到最佳效果!
===========================================================
这样做意义何在???Top
22 楼fxs_2008()回复于 2007-01-01 19:14:04 得分 0
我查了不少文章,说cookie和session结合用才能最好!但究竟如何结合,没有文章指出!
但大家却都说两者结合用最好!
结合用:我的理解是,既可以用cookie的特点,也可以用session的特点!
问题如下:
1、如果客户不需要单独保存一个cookie周期,那直接用session好了!每次登录成功后设session变量,只验证session;
2、如果用户需要设一个cookie存活期,比如,两周内,不用登录可直接验证!那如何办呢?session好像解决不了这个问题,不少文章都推荐,直接用cookie,不要用session了。因为session和cookie的同步只有浏览器周期。我测试发现,实际上,session和cookie的同步只是因为有同一个ID,另一个就是可能和缓存有关!
如果关闭浏览器,缓存就没有了,ID下次打开浏览器时只要遇session_start();就会改变——即重写cookie。且同时将cookie的周期设为0。这意味即使你以前设过cookie周期,也没有用了。
所以,试图能过设cookie的存活期来实现下次验证时不用登录行不通(可能在第二次是行,但第三次就不行了)
3、解决问题第三种办法:实现用户自定义免登录期限,且同时用session.同时用session实现以下两种情况:
如果用户要求免登录期限,用非默认session_name()——phpsessiD的保存cookie名及ID。并以下次验证时将ID取回,用这ID初始化session,从session文件中取变量验证!
如果用户登录时没有要求免登录期限,则登录成功后直接设session变量。在浏览器周期验证session.
上面的关键在于,客户端cookie只保存ID,通过这个ID和session沟通。从而既实现安全,又实现多种验证需求!
上面这个问题的误区是:cookie周期和session周期是同步的。实际上也只是在浏览器周期同步。关闭浏览器,两者不相关。——目前我测试中还有找到有相关的地方,各位可测试看看!
因此,我认为,session_set_cookie_params(),来设cookie的周期是没有用的。
setcookie(session_name(),session_id(),$lifetime,"/");这个语句也没有用。因为只要遇session_start(),它就归零!但你只要用session,就不能不用session_start(),所以它没有意义。
Top
23 楼fxs_2008()回复于 2007-01-01 19:25:13 得分 0
总结一下:
1、要求是只用在客户端存sessionID实现客户可设免登录期验证;
2、cookie周期和session周期不同步,或可理解为不相关。cookie周期是手设或系统指定(系统批定的话所有cookie保存期就一样);session周期与垃圾清理机制有关。
所以,要用既用、cookie周期和session周期,session周期应>cookie周期;
3、通过用其他cookie名保存sessionID,以免被覆盖。并这个ID实现与 session通信并验证!
不知我说的是否明白,大家是否有更好的办法?也是进一步测试中。Top
24 楼zhys9(OoP.plorer)回复于 2007-01-01 23:50:40 得分 0
不明白。...Top
25 楼helloyou0(你好!)回复于 2007-01-02 11:48:51 得分 0
上面的关键在于,客户端cookie只保存ID,通过这个ID和session沟通。从而既实现安全,又实现多种验证需求!
-------------------------------------------
就问一句, 既然客户端只保存ID, 那么我看到你电脑上的cookie中保存的ID后,在我的电脑上伪造一个同样ID的cookie, 服务端如何辨别?Top
26 楼helloyou0(你好!)回复于 2007-01-02 11:59:52 得分 0
上面的问题问得不好. 做废
Top
27 楼fxs_2008()回复于 2007-01-02 12:01:58 得分 0
回helloyou0(你好!) :
这个是cookie通病了,如果只用cookie,你仍然会遇到这样的问题!cookie没法解决!最多是加密(我没试过)。
保证cookie安全,1是用设变量,2是设有效期,3是加密;但这仍然会被盗用。
用session且在客户端保存ID,这说明除了具有cookie的安全后,还要用session的安全。即使客户端ID是正确的,还要看session文件是否存在,看session文件中的变量是否存在,是否过期。
如果session文件不存在,这个ID就没用了。
如果session文件中的某个验证变量不存,这个ID也没有用了,必须重新登录设session变量
Top
28 楼fxs_2008()回复于 2007-01-02 12:17:54 得分 0
其实,我上面说了这么多,就想解决一点,如何用session实现免登录验证!比如:用户选择两周内不用登录即可验证,不知道大家都是如何解决这个问题的!Top




