当前位置:  编程语言>php

php session 原理详解,用法介绍以及如何设置过期时间

 
    发布时间:2016-10-10  


    本文导语: php session 原理详解,用法介绍以及如何设置过期时间 (本文由www.搜集整理)彻底理解PHP的SESSION机制 PHP session 变量用于存储有关用户会话的信息,或更改用户会话的设置。Session 变量保存的信息是单一用户...

 php session 原理详解,用法介绍以及如何设置过期时间 (本文由www.169it.com搜集整理)


彻底理解PHP的SESSION机制

      PHP session 变量用于存储有关用户会话的信息,或更改用户会话的设置。Session 变量保存的信息是单一用户的,并且可供应用程序中的所有页面使用。PHP session用法其实很简单它可以把用户提交的数据全局变量形式保存在一个session中并且会生成一个唯一的session_id,这样就是为了多了不会产生混乱了,并且session中同一浏览器同一站点只能有一个session_id。Session 的工作机制是:为每个访问者创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,亦或通过 URL 进行传导。

 PHP Session 变量

      当您运行一个应用程序时,您会打开它,做些更改,然后关闭它。这很像一次会话。计算机清楚你是谁。它知道你何时启动应用程序,并在何时终止。但是在因特网上,存在一个问题:服务器不知道你是谁以及你做什么,这是由于 HTTP 地址不能维持状态。,通过在服务器上存储用户信息以便随后使用。不过,会话信息是临时的,在用户离开网站后将被删除。如果您需要永久储存信息,可以把数据存储数据库中。

一、php的session的默认机制就是用磁盘文件来实现php会话。php.ini配置:session.save_handler = files

  1、session_start()

    1.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"

              //这是随机分级存储,这个样的话,垃圾回收将不起作用,需要自己写脚本

    1.2  session会判断当前是否有$_COOKIE[session_name()];session_name()返回保存session_id的COOKIE键值,这个值可以从php.ini找到.

              session.name = PHPSESSID //默认值PHPSESSID 

    1.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,//默认为空

                          )

    1.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.         

 if (isset($_COOKIE[session_name()])) 
 {
     setcookie(session_name(),'',time() -42000,'/');//旧session cookie过期
  }
  session_regenerate_id();//这一步会生成新的session_id
  //session_id()返回的是新的值

   3、 写入SESSION操作

    在脚本结束的时候会执行SESSION写入操作,把$_SESSION中值写入到session_id命名的文件中,可能已经存在,

    可能需要创建新的文件。

 4、 销毁SESSION

    SESSION发出去的COOKIE一般属于即时COOKIE,保存在内存中,当浏览器关闭后,才会过期,假如需要人为强制过期,

    比如 退出登录,而不是关闭浏览器,那么就需要在代码里销毁SESSION,方法有很多,

            1. setcookie(session_name(),session_id(),time() -8000000,..);//退出登录执行.

            2. usset($_SESSION);//这会删除所有的$_SESSION数据,刷新后,有COOKIE传过来,但是没有数据。

            3. session_destroy();//这个作用更彻底,删除$_SESSION 删除session文件,和session_id.

    当不关闭浏览器的情况下,再次刷新,2和3都会有COOKIE传过来,但是找不到数据.

二、由用户自定义session处理机制。相应的php.ini配置: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步。

如何设置PHP的SESSION的过期时间或者有效期

      php中的session有效期默认是1440秒(24分钟),也就是说,客户端超过24分钟没有刷新,当前session就会失效。当然如果用户关闭了浏览器,会话也就结束了,session自然也不存在了!   session储存在服务器端,根据客户端提供的sessionid来得到这个用户的文件,然后读取文件,取得变量的值,sessionid可以使用客户端的cookie或者http1.1协议query_string(就是访问的url的“?”后面的部分)来传送给服务器,然后服务器读取session的目录……

     要控制Session的生命周期,首先我们需要了解一下php.ini关于Session的相关设置(打开php.ini文件,在“[Session]”部分):

1、session.use_cookies:默认的值是“1”,代表SessionID使用Cookie来传递,反之就是使用Query_String来传递;

2、session.name:这个就是SessionID储存的变量名称,可能是Cookie,也可能是Query_String来传递,默认值是“PHPSESSID”;

3、session.cookie_lifetime:这个代表SessionID在客户端Cookie储存的时间,默认是0,代表浏览器一关闭SessionID就作废……就是因为这个所以Session不能永久使用!

4、session.gc_maxlifetime:这个是Session数据在服务器端储存的时间,如果超过这个时间,那么Session数据就自动删除

    还有很多的设置,不过和本文相关的就是这些了,下面开始讲如何设置Session的存活周期。

前面说过,服务器通过SessionID来读取Session的数据,但是一般浏览器传送的SessionID在浏览器关闭后就没有了,那么我们只需要人为的设置SessionID并且保存下来,不就可以……

     如果你拥有服务器的操作权限,那么设置这个非常非常的简单,只是需要进行如下的步骤:

1、把“session.use_cookies”设置为1,使用Cookie来储存SessionID,不过默认就是1,一般不用修改

2、把“session.cookie_lifetime”改为你需要设置的时间(比如一个小时,就可以设置为3600,以秒为单位);

3、把“session.gc_maxlifetime”设置为和“session.cookie_lifetime”一样的时间;

      在PHP的文档中明确指出,设定session有效期的参数是session.gc_maxlifetime。可以在php.ini文件中,或者通过ini_set()函数来修改这一参数。问题在于,经过多次测试,修改这个参数基本不起作用,session有效期仍然保持24分钟的默认值。

      由于PHP的工作机制,它并没有一个daemon线程,来定时地扫描session信息并判断其是否失效。当一个有效请求发生时,PHP会根据全局变量

session.gc_probability/session.gc_divisor(同样可以通过php.ini或者ini_set()函数来修改)的值,来决定是否启动一个GC(Garbage Collector)。

        默认情况下,session.gc_probability = 1,session.gc_divisor =100,也就是说有1%的可能性会启动GC。GC的工作,就是扫描所有的session信息,用当前时间减去session的最后修改时间(modified date),同session.gc_maxlifetime参数进行比较,如果生存时间已经超过gc_maxlifetime,就把该session删除。

       到此为止,工作一切正常。那为什么会发生gc_maxlifetime无效的情况呢?

       在默认情况下,session信息会以文本文件的形式,被保存在系统的临时文件目录中。在Linux下,这一路径通常为tmp,在 Windows下通常为C:WindowsTemp。当服务器上有多个PHP应用时,它们会把自己的session文件都保存在同一个目录中。同样地,这些PHP应用也会按一定机率启动GC,扫描所有的session文件。

      问题在于,GC在工作时,并不会区分不同站点的session。举例言之,站点A的gc_maxlifetime设置为2小时,站点B的 gc_maxlifetime设置为默认的24分钟。当站点B的GC启动时,它会扫描公用的临时文件目录,把所有超过24分钟的session文件全部删除掉,而不管它们来自于站点A或B。这样,站点A的gc_maxlifetime设置就形同虚设了。

      找到问题所在,解决起来就很简单了。修改session.save_path参数,或者使用session_save_path()函数,把保存session的目录指向一个专用的目录,gc_maxlifetime参数工作正常了。

      还有一个问题就是,gc_maxlifetime只能保证session生存的最短时间,并不能够保存在超过这一时间之后session信息立即会得到删除。因为GC是按机率启动的,可能在某一个长时间内都没有被启动,那么大量的session在超过gc_maxlifetime以后仍然会有效。

       解决这个问题的一个方法是,把session.gc_probability/session.gc_divisor的机率提高,如果提到100%,就会彻底解决这个问题,但显然会对性能造成严重的影响。另一个方法是自己在代码中判断当前session的生存时间,如果超出了 gc_maxlifetime,就清空当前session。

与php session 相关的函数

session_abort — Discard session array changes and finish session
session_cache_expire — Return current cache expire
session_cache_limiter — Get and/or set the current cache limiter
session_commit — Alias of session_write_close
session_create_id — Create new session id
session_decode — Decodes session data from a session encoded string
session_destroy — Destroys all data registered to a session
session_encode — Encodes the current session data as a session encoded string
session_gc — Perform session data garbage collection
session_get_cookie_params — Get the session cookie parameters
session_id — Get and/or set the current session id
session_is_registered — Find out whether a global variable is registered in a session
session_module_name — Get and/or set the current session module
session_name — Get and/or set the current session name
session_regenerate_id — Update the current session id with a newly generated one
session_register_shutdown — Session shutdown function
session_register — Register one or more global variables with the current session
session_reset — Re-initialize session array with original values
session_save_path — Get and/or set the current session save path
session_set_cookie_params — Set the session cookie parameters
session_set_save_handler — Sets user-level session storage functions
session_start — Start new or resume existing session
session_status — Returns the current session status
session_unregister — Unregister a global variable from the current session
session_unset — Free all session variables
session_write_close — Write session data and end session


php使用session实例

php使用session举例1,php使用session来保存用户登录信息具体步骤如下:

1、数据库连接配置页面:connectvars.php

<?php
//数据库的位置
define('DB_HOST', 'localhost');
//用户名
define('DB_USER', 'root');
//口令
define('DB_PASSWORD', '19900101');
//数据库名
define('DB_NAME','test') ;
?>

2、登录页面:logIn.php

<?php
//插入连接数据库的相关信息
require_once 'connectvars.php';
//开启一个会话
session_start();
$error_msg = "";
//如果用户未登录,即未设置$_SESSION['user_id']时,执行以下代码
if(!isset($_SESSION['user_id'])){
    if(isset($_POST['submit'])){//用户提交登录表单时执行如下代码
        $dbc = mysqli_connect(DB_HOST,DB_USER,DB_PASSWORD,DB_NAME);
        $user_username = mysqli_real_escape_string($dbc,trim($_POST['username']));
        $user_password = mysqli_real_escape_string($dbc,trim($_POST['password']));
        if(!empty($user_username)&&!empty($user_password)){
            //MySql中的SHA()函数用于对字符串进行单向加密
            $query = "SELECT user_id, username FROM mismatch_user WHERE username = '$user_username' AND "."password = SHA('$user_password')";
            //用用户名和密码进行查询
            $data = mysqli_query($dbc,$query);
            //若查到的记录正好为一条,则设置SESSION,同时进行页面重定向
            if(mysqli_num_rows($data)==1){
                $row = mysqli_fetch_array($data);
                $_SESSION['user_id']=$row['user_id'];
                $_SESSION['username']=$row['username'];
                $home_url = 'loged.php';
                header('Location: '.$home_url);
            }else{//若查到的记录不对,则设置错误信息
                $error_msg = 'Sorry, you must enter a valid username and password to log in.';
            }
        }else{
            $error_msg = 'Sorry, you must enter a valid username and password to log in.';
        }
    }
}else{//如果用户已经登录,则直接跳转到已经登录页面
    $home_url = 'loged.php';
    header('Location: '.$home_url);
}
?>
<html>
    <head>
        <title>Mismatch - Log In</title>
        <link rel="stylesheet" type="text/css" href="/it-php/style.css" />
    </head>
    <body>
        <h3>Msimatch - Log In</h3>
        <!--通过$_SESSION['user_id']进行判断,如果用户未登录,则显示登录表单,让用户输入用户名和密码-->
        <?php
        if(!isset($_SESSION['user_id'])){
            echo '<p class="error">'.$error_msg.'</p>';
        ?>
        <!-- $_SERVER['PHP_SELF']代表用户提交表单时,调用自身php文件 -->
        <form method = "post" action="/it-php/</php echo $_SERVER[/.html">
            <fieldset>
                <legend>Log In</legend>
                <label for="username">Username:</label>
                <!-- 如果用户已输过用户名,则回显用户名 -->
                <input type="text" id="username" name="username"
                value="<?php if(!empty($user_username)) echo $user_username; ?>" />
                <br/>
                <label for="password">Password:</label>
                <input type="password" id="password" name="password"/>
            </fieldset>
            <input type="submit" value="Log In" name="submit"/>
        </form>
        <?php
        }
        ?>
    </body>
</html>

3、登入页面:loged.php

<?php
//使用会话内存储的变量值之前必须先开启会话
session_start();
//使用一个会话变量检查登录状态
if(isset($_SESSION['username'])){
    echo 'You are Logged as '.$_SESSION['username'].'<br/>';
    //点击“Log Out”,则转到logOut页面进行注销
    echo '<a href="/it-php/logOut.html"> Log Out('.$_SESSION['username'].')</a>';
}
/**在已登录页面中,可以利用用户的session如$_SESSION['username']、
 * $_SESSION['user_id']对数据库进行查询,可以做好多好多事情*/
?>

4、注销session页面:logOut.php(注销后重定向到lonIn.php)


<?php
//即使是注销时,也必须首先开始会话才能访问会话变量
session_start();
//使用一个会话变量检查登录状态
if(isset($_SESSION['user_id'])){
    //要清除会话变量,将$_SESSION超级全局变量设置为一个空数组
    $_SESSION = array();
    //如果存在一个会话cookie,通过将到期时间设置为之前1个小时从而将其删除
    if(isset($_COOKIE[session_name()])){
        setcookie(session_name(),'',time()-3600);
    }
    //使用内置session_destroy()函数调用撤销会话
    session_destroy();
}
//location首部使浏览器重定向到另一个页面
$home_url = 'logIn.php';
header('Location:'.$home_url);
?>


php使用session实例2, 用户自定义session处理机制


      //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);
          }
        }
        returntrue;
      }


相关文章推荐:


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3