zoukankan      html  css  js  c++  java
  • 禁止COOKIE后对SESSION的影响

    一.理解SESSION机制

      简单来说:每一个SESSION都有一个唯一的session_id , 默认情况下,session_id存储在客户端(默认COOKIE['PHPSESSID']),

       在使用SESSION的时候会先从客户端读取相应的SESSION_ID,如果客户端禁止使用SESSION将不能按照默认的方式来使用SESSION

    1.session.save_handler = files(这是php.ini中的一条配置)
        * 1 . session_start ()
             (1) session_start ()是session机制的开始,它有一定概率开启垃圾回收 , 因为session是存放在文件中,
    PHP自身的垃圾回收是无效的,SESSION的回收是要删文件的,这个概率是根据php . ini的配置决定的,
    但是有的系统是 session . gc_probability = 0 ,这也就是说概率是0,而是通过cron脚本来实现垃圾回收。 

    session . gc_probability = 1 
    session . gc_divisor = 1000 
    session . gc_maxlifetime = 1440 // 过期时间 默认24分钟

                概率是 session.gc_probability/session.gc_divisor 结果 1/1000,
                不建议设置过小,因为session的垃圾回收,是需要检查每个文件是否过期的。       

    session . save_path ="不同的系统有不同设置"

       好像不同的系统默认不一样,有一种设置是 "N;/path"
               这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本
             (2)  session会判断当前是否有 $_COOKIE [ session_name ()]; session_name ()返回保存session_id的COOKIE键值,
    这个值可以从php . ini找到            

    session . name = PHPSESSID // 默认值PHPSESSID 

             (3)  如果不存在会生成一个session_id , 然后把生成的session_id作为COOKIE的值传递到客户端 . 

    相当于执行了下面COOKIE 操作,注意的是,这一步执行了setcookie()操作,COOKIE是在header头中发送的,
    这之前是不能有输出的,PHP有另外一个函数 session_regenerate_id () 如果使用这个函数,这之前也是不能有输出的。               

     setcookie (
          session_name () , session_id () , session . cookie_lifetime , // 默认0 session . cookie_path , // 默认'/'当前程序跟目录下都有效 session . cookie_domain , // 默认为空 )

            (4)  如果存在那么session_id = $_COOKIE [ session_name ];

                然后去session . save_path指定的文件夹里去找名字为 ' SESS_ ' . session_id ()的文件 .
                读取文件的内容反序列化,然后放到 $_SESSION中


        * 2 . 为 $_SESSION赋值
          比如新添加一个值 $_SESSION [ ' test ' ] = ' blah ' ; 那么这个 $_SESSION只会维护在内存中 ,当脚本执行结束的时候,
    用把 $_SESSION的值写入到session_id指定的文件夹中 ,然后关闭相关资源 .       这个阶段有可能执行更改session_id的操作,
    比如销毁一个旧的的session_id,生成一个全新的session_id . 一半用在自定义 session操作,角色的转换上,
    比如Drupal . Drupal的匿名用户有一个SESSION的,当它登录后需要换用新的session_id

       session_regenerate_id — 使用新生成的会话 ID 更新现有会话 ID   

       ession_name — 读取/设置会话名称

       session_id — 获取/设置当前会话 ID   

    if ( isset ( $_COOKIE [ session_name ()])) {
              setcookie ( session_name () , '' , time () - 42000 , ' / ' ); // 旧session cookie过期 
            }
    session_regenerate_id (); //和下面的代码是一个意思,会更新当前对话的sess_id
    // 这一步会生成新的session_id
    //session_id()返回的是新的值 
    <?php  
        session_start();//开始使用SESSION
        echo session_id();//获取当前会话中的session的ID
        echo '<hr>';
        echo session_name();//获取当前会话中的SESSION的NAME
        setcookie(session_name(), '', time()-4200, '/');//设置客户端中存储的session id
    
        // 这样会连续生成很多session文件
    ?>

      session与垃圾回收机制,可以设置(1)中php.ini的参数,设置服务器对SESSION文件的清理频率

      3 . 写入SESSION操作

          在脚本结束的时候会执行SESSION写入操作,把 $_SESSION中值写入到session_id命名的文件中 ,可能已经存在,
    可能需要创建新的文件。
        * 4 . 销毁SESSION
          SESSION发出去的COOKIE一般属于即时COOKIE,保存在内存中,当浏览器关闭后,才会过期,假如需要人为强制过期,
    比如 退出登录,而不是关闭浏览器,那么就需要在代码里销毁SESSION,方法有很多,
              o 1 . setcookie ( session_name () , session_id () , time () - 8000000 , .. ); // 退出登录前执行
              o 2 . usset( $_SESSION ); // 这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。
              o 3 . session_destroy (); // 这个作用更彻底,删除$_SESSION 删除session文件,和session_id

          当不关闭浏览器的情况下,再次刷新,2和3都会有COOKIE传过来,但是找不到数据
    2.session.save_handler = user
          用户自定义session处理机制,更加直观
        * session_set_save_handler ( ' open ' , ' close ' , ' read ' , ' write ' , ' destroy ' , ' gc ' );
      1 . session_start () ,
            执行open( $save_path , $session_name )打开session操作句柄
            $save_path 在session . save_handler = files的情况下它就是session . save_path,
        但是如果用户自定的话,这个两个参数都用不上,直接返回TRUE

            执行read( $id )从中读取数据 . // 这个参数是自动传递的就是session_id(),可以通过这个值进行操作。
        * 2 . 脚本执行结束
            执行write( $id , $sess_data ) // 两个参数,很简单
        * 3 . 假如用户需要session_destroy()
            先执行destroy.在执行第2步

    //SESSION初始化的时候调用
          function open($save_path, $session_name)
          {
            global $sess_save_path;
            $sess_save_path = $save_path;
            return(true);
          }
    
          //关闭的时候调用
          function close()
          {
            return(true);
          }
    
          function read($id)
          {
            global $sess_save_path;
            $sess_file = "$sess_save_path/sess_$id";
            return (string) @file_get_contents($sess_file);
          }
          //脚本执行结束之前,执行写入操作
          function write($id, $sess_data)
          {
            echo "sdfsf";
            global $sess_save_path;
    
            $sess_file = "$sess_save_path/sess_$id";
            if ($fp = @fopen($sess_file, "w")) {
              $return = fwrite($fp, $sess_data);
              fclose($fp);
              return $return;
            } else {
              return(false);
            }
    
          }
    
          function destroy($id)
          {
            global $sess_save_path;
    
            $sess_file = "$sess_save_path/sess_$id";
            return(@unlink($sess_file));
          }
    
          function gc($maxlifetime)
          {
            global $sess_save_path;
    
            foreach (glob("$sess_save_path/sess_*") as $filename) {
              if (filemtime($filename) + $maxlifetime < time()) {
                @unlink($filename);
              }
            }
            return true;
    }

    session与cookie区别:

           为什么会有cookie呢,大家都知道,http是无状态的协议,客户每次读取web页面时,服务器都打开新的会话,而且服务器也不会自动维护客户的上下文信息。

            session就是一种保存上下文信息的机制,它是针对每一个用户的,变量的值保存在服务器端,通过SessionID来区分不同的客户,session是以cookie或URL重写为基础的,默认使用cookie来实现,系统会创造一个名为 PHPSESSID的输出cookie,我们叫做session cookie; 以区别persistent cookies,也就是我们通常所说的cookie,注意session cookie是存储于浏览器内存中的,并不是写到硬盘上的,这也就是我们刚才看到的JSESSIONID,我们通常情是看不到JSESSIONID的。

            但是当我们把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,我们就可以在地址栏看到 sessionid=KWJHUG6JJM65HS2K6之类的字符串。

             明白了原理,我们就可以很容易的分辨出persistent cookies和session cookie的区别了,网上那些关于两者安全性的讨论也就一目了然了,session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本(通常是加密的),而且可能会遭到cookie欺骗以及针对cookie的跨站脚本攻击,自然不如 session cookie安全了。

             通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的sessionid,这样我们信息共享的目的就达不到 了,此时我们可以先把sessionid保存在persistent cookie中,然后在新窗口中读出来,就可以得到上一个窗口SessionID了,这样通过session cookie和persistent cookie的结合我们就实现了跨窗口的session tracking(会话跟踪)。

             在一些web开发的书中,往往只是简单的把Session和cookie作为两种并列的http传送信息的方式,session cookies位于服务器端,persistent cookie位于客户端,可是session又是以cookie为基础的,明白的两者之间的联系和区别,我们就不难选择合适的技术来开发web service了。

    二.php.ini配置

      我们都知道当在session 会话有基于cookie和基于url两种传递SESSIONID的方法。为了实现客户端禁止cookie发送的情况也不影响客户登陆网站,可以设置 php.ini中 session.use_trans_sid=1 ,表示当客户端浏览器禁止cookie的时候,页面上的链接会基于url传递SESSIONID。但是很多人仅仅设置了这一个选项并没有达到效果,本人也 遇到此问题,后来一番研究发现
    php.ini 文件中还有两个选项
        session.use_cookies=1
        session.use_only_cookies=1
      仔细琢磨上面的英文就会发现其意义
        session.use_cookies表示是否开始基于cookies的session会话
        session.use_only_cookies 表示是否只开启基于cookies的session的会话方式  
      所以如果想要在浏览器开启cookie的时候用基于cookie的方式,在未开启cookie的时候使用url的方式就进行如下设置(最常用的方式,推荐)
      在php.ini文件中
        session.use_trans_sid=1
        session.use_only_cookies=0
        session.use_cookies=1  
      或者 在php程序中
        ini_set(“session.use_trans_sid”,”1″);
        ini_set(“session.use_only_cookies”,0);
        ini_set(“session.use_cookies”,1);
      如果不管浏览器是否开启cookie,都使用url的方式就进行如下设置(这个例子主要想说明一下设置session.use_only_cookies 和 session.use_cookies的区别)
      在php.ini文件中
        session.use_trans_sid=1
        session.use_only_cookies=0
        session.use_cookies=0
      或者 在php程序中
        ini_set(“session.use_trans_sid”,”1″);
        ini_set(“session.use_only_cookies”,0);
        ini_set(“session.use_cookies”,0);
      动手自己试一试 你就会明白session.use_only_cookies 和 session.use_cookies的区别。

    三.总结

    主要利用的函数:

      session_id();----用来设置要用的SESSION的会话ID,在php.ini配置允许的情况下;必须在session_start()之前启用

      以URL重写方式会话的代码

    <?php  
        if($_GET['sess_id']){
            session_id($_GET['sess_id']);    
        }
        session_start();//开始使用SESSION,如果要自己设置(比如URL重写方式), 要在sesstion_start()前边,否则将不能设置新的sess_id
        $_SESSION['name'] = 'this is a test2222';
        echo $_SESSION['name'];
        //当浏览器禁止cookie后,每次加载SESSION都会建立新的文件,这样就不能实现会话的功能了
    ?>

      

  • 相关阅读:
    动态传参
    函数的介绍
    文件的操作
    send email with formatted table
    minimize and close window with customed winform
    python algorithm
    something important about docker
    book list
    which language is suitable for what to do
    Find Duplicate Items in list fast
  • 原文地址:https://www.cnblogs.com/zhengfengyun/p/6037819.html
Copyright © 2011-2022 走看看