CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  Web 开发 >  PHP

高手路过不要错过:Session最难的两个问题?

楼主fxs_2008()2006-12-26 18:25:32 在 Web 开发 / PHP 提问

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

相关问题

关键词

得分解答快速导航

  • 帖主:fxs_2008
  • MAD_FROG
  • hnxxwyq
  • yueliangdao0608
  • ice_berg16
  • Meteorlet
  • ashchen
  • Meteorlet
  • ashchen
  • ashchen
  • helloyou0

相关链接

  • Web开发类图书

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo