会话控制的思想是指能够在网站中根据一个会话跟踪用户。
     PHP的会话是通过唯一的会话ID来驱动的。会话ID是一个加密的随机数字。它由PHP生成,在会话的生命周期中都会保存在客户端。它可以保存在用户机器的cookie中,或者通过URL在网络上传递。
1 cookie
1.1 什么是cookie
     cookie就是一小段信息,可以由脚本在客户端机器保存。可以通过发送一个如下格式的HTTP标题头,从而在用户端机器设置一个cookie:
Set-Cookie: NAME = VALUE; [expires = DATE;] [path = PATH;] [domain = DOMAIN_NAME;] [secure]
 
     这条语句创建一个名为NAME,值为VALUE的cookie。除了该参数,其他参数都是可选的。expires域设置该cookie失效日期(请注意:如果失效日期不设置,cookie将永远有效,如果不手动将其删除的话)。path和domain域合起来指定URL或与cookie相关的URL。secure关键字的意思是在普通的HTTP链接中不发送cookie。
     当浏览器链接一个URL时,首先要搜索当地保存的cookie。如果有任何与正在连接的URL相关的cookie,浏览器将它提交到服务器。
 
1.2 通过PHP设置cookie
     使用setcookie()函数在PHP中手动设置cookie。函数原型如下:
bool setcookie(string name [, string value [, int expire [, string path [, string domain [, int secure]]]]])
 
     如果按如下方式设置一个cookie: setcookie('mycookie', 'value');
     当用户访问站点中的下一页(或者重载当前页)的时候,可以通过名为$_COOKIE['mycookie']来实现。
     可以调用setcookie()来删除一个cookie,setcookie()中的参数为要删除的cookie名称和已经过去的到期时间。也可以使用前面给出的cookie语法并通过header()函数来手动设置cookie。注意:cookie标题头必须在发送其他标题头之前发送,否则就无效(这是cookie的限制,而不是PHP的限制)。
 
1.3 在会话中使用cookie
     当使用PHP会话的时候,不必手动设置cookie。可以使用session_get_cookie_params()来查看由会话控制设置的cookie内容。它将返回包含元素lifetime、path、domain和secure的相关数组。也可以使用:session_set_cookie_params($lifetime, $path, $domain [, $secure]); 来设置会话cookie的参数。
 
1.4 存储会话ID
     默认情况下,PHP将在会话中使用cookie。如果可能,可以设置一个cookie用来存储会话ID。
     另一个使用会话ID的方法是将会话ID添加到URL中。如果在php.ini文件设置了session,use_trans_sid指令,则可以自动实现它。
 
 
2 实现简单的会话
使用会话的基本步骤如下:
1.开始一个会话
2.注册会话变量
3.使用会话变量
4.注销变量并销毁会话
 
2.1 开始一个会话
     在使用会话功能前,必须开始一个会话。
(1)调用session_start()函数
     该函数会检查是否有一个会话ID存在,如果不存在,就创建一个,并且使其能够通过超级全局数组$_SESSION进行访问。如果已经存在,将这个已经注册的会话变量载入以便使用。
     你必须在使用会话的脚本开始部分调用session_start()函数。如果没有调用这个函数,所有保存在该会话的信息都无法在脚本中使用。
(2)将PHP设置成当有用户访问网站的时候就自动启动一个会话
     使用php.ini文件中的session.auto_start选项完成该设置。该方法有个很大的缺点:启用auto_start设置导致无法使用对象作为会话变量。这是因为该对象的类定义必须在创建该对象的会话开始之前载入。
 
2.2 注册一个会话变量
     要创建一个会话变量,只需在这些数组中设置一个元素,如下:$_SESSION['myvar'] = 5; 创建的会话变量只有在会话经书或手动重置它时才会失效。
 
2.3 使用会话变量
     在检查会话变量是否已经被设置时(例如,通过isset()函数或者empty()函数),必须非常小心。请记住,变量可以被用户通过GET和POST设置。可以通过检查$_SESSION数组来确定一个变量是否是注册的会话变量:if(isset($_SESSION['myvar'])) ……
 
2.4 注销变量与销毁会话
     通过注销$_SESSION数组的适当元素,可以直接注销该变量:unset($_SESSION['myvar']);
     不能销毁这个$_SESSION数组,因为这样将禁用会话功能。要一次销毁所有的会话变量,可以使用:$_SESSION = array();
     当使用完一个会话后,首先应该销毁所有的变量,然后再调用:session_destroy(); 来清除会话ID。
 
3一个简单的会话(实例)
 
三个脚本:auto-main.php提供登陆表单并为成员提供身份验证,members_only.php指向成功登陆的显示信息,logout.php用户退出登陆。
3.1 auto-main.php
<?php
session_start();
 
if(isset ($_POST['userid' ]) && isset($_POST['password'])){
      $userid = $_POST[ 'userid'];
      $password = $_POST[ 'password'];
      
      $db_conn = new mysqli('localhost' , 'root' , '' , 'test' );
      
      if(mysqli_connect_error()){
             echo "Connection to database failed:" . mysqli_connect_errno();
             exit();
      }
      
      $query = "select * from authorized_users" . " where name = '$userid'" . "and password = ' $password'" ;
 
      $result = $db_conn -> query($query);
      
      if($result -> num_rows > 0){
            $_SESSION[ 'valid_user'] = $userid;
      }
      $db_conn -> close();
}
 
?>
<html>
      <body >
             <h1 >Home Page </h1 >
             <?php
                   ifisset($_SESSION[ 'valid_user'])){
                         echo 'You are logged in as: ' . $_SESSION['valid_user'] . '<br />' ;
                         echo '<a href="logout.php">Log out</a><br />';
                  } else {
                         ifisset($userid)){ //失败
                               echo 'Could not log you in.<br />';
                        } else {
                               echo 'You are not logged in.<br />';
                        }
                  }
                  
                   echo '<form method="post" action="auto-main.php">
                              <table>
                                    <tr>
                                          <td>Userid:</td>
                                          <td><input type="text" name="userid"></td>
                                    </tr>
                                    <tr>
                                          <td>Password:</td>
                                          <td><input type="password" name="password"></td>
                                    </tr>
                                    <tr>
                                          <td colspan="2" align="center"><input type="submit" value="Log in"></td>
                                    </tr>
                              </table>
                        </form>' ;
             ?>
             <br />
             <a href ="members-only.php"> Members section</ a>
      </body >
</html>
 
 
3.2 members_only.php
<?php
session_start();
 
echo "<h1>Members only</h1>";
 
if(isset ($_SESSION['valid_user' ])){
      echo "<p>You are logged in as " . $_SESSION['valid_user' ] . "</p>";
      echo "<p>Member only content goes here </p>" ;
else {
      echo "<p>You are not logged in.</p>" ;
}
 
echo "<a href='auto-main.php'>Back to main page</p>";
?>
 
 
3.3 logout.php
<?php
session_start();
 
$old_user = $_SESSION['valid_user'];
unset($old_user);
 
session_destroy();
 
?>
<html>
      <body >
             <h1 >Log out </h1 >
             <?php
                   if(! empty($old_user)){
                         echo 'Logged out.<br />';
                  } else {
                         echo 'You were not logged in, and so have not been logged out.<br />';
                  }
             ?>
             <a href ="auto-main.php"> Back to main page</ a>
      </body >
</html>
 
 
4 session
4.1 影响session数据的PHP函数或事件

(1) session_start() 初始化session,生命周期的开始。

     session初始化操作,声明一个全局数组$_SESSION,映射寄存在内存的session数据。如果session文件已经存在,并且保存有session数据,session_start()则会读取session数据,填入$_SESSION中,开始一个新的session生命周期。
(2) $_SESSION
      它是一个全局变量,类型是Array,映射了session生命周期的session数据,寄存在内存中。在session初始化的时候,从session文件中读取数据,填入该变量中。在session生命周期结束时,将$_SESSION数据写回session文件。
(3) session_register()
      在session生命周期内,使用全局变量名称将注全局变量注册到当前session中。所谓注册,就是将变量填入$_SESSION中,值为NULL。它不会对session文件进行任何IO操作,只是影响$_SESSION变量。注意,它的正确写法是session_register(‘varname’),而不是session_register($varname)
(4) session_unregister()
      与session_register操作正好相反,即在session生命周期,从当前session注销指定变量。同样只影响$_SESSION,并不进行任何IO操作。
(5) session_unset()
      在session生命周期,从当前session中注销全部session数据,让$_SESSION成为一个空数组。它与unset($_SESSION)的区别在于:unset直接删除$_SESSION变量,释放内存资源;另一个区别在于,session_unset()仅在session生命周期能够操作$_SESSION数组,而unset()则在整个页面(page)生命周期都能操作$_SESSION数组。session_unset()同样不进行任何IO操作,只影响$_SESSION数组。
(6) session_destroy()
      如果说session_start()初始化一个session的话,而它则注销一个session。意味着session生命周期结束了。在session生命周期结整后,session_register, session_unset, session_register都将不能操作$_SESSION数组,而$_SESSION数组依然可以被unset()等函数操作。这时,session意味着是未定义的,而$_SESSION依然是一个全局变量,他们脱离了关映射关系。
通过session_destroy()注销session,除了结束session生命周期外,它还会删除sesion文件,但不会影响当前$_SESSION变量。即它会产生一个IO操作。
(7) session_regenerate_id()
      调用它,会给当前用户重新分配一个新的session id。并且在结束当前页面生命周期的时候,将当前session数据写入session文件。前提是,调用此函数之前,当前session生命周期没有被终止(参考第9点)。它会产生一个IO操作,创建一个新的session文件,创建新的session文件的是在session结束之前,而不是调用此函数就立即创建新的session文件。
(8) session_commit()
      session_commit()函数是session_write_close()函数的别名。它会结束当前session的生命周期,并且将session数据立即强制写入session文件。不推荐通过session_commit()来手工写入session数据,因为PHP会在页面生命周期结束的时候,自动结束当前没有终止的session生命周期。它会产生一个IO写操作
(9) end session
      结束session,默认是在页面生命周期结束的之前,PHP会自动结束当前没有终止的session。但是还可以通过session_commit()与session_destroy()二个函数提前结束session。不管是哪种方式,结束session都会产生IO操作,分别不一样。默认情况,产生一个IO写操作,将当前session数据写回session文件。session_commit()则是调用该函数那刻,产生一个IO写操作,将session数据写回session文件。而session_destroy()不一样在于,它不会将数据写回session文件,而是直接删除当前session文件。有趣的是,不管是session_commit(),还是session_destroy()都不会清空$_SESSION数组,更不会删除$_SESSION数组,只是所有session_*函数不能再操作session数据,因为当前的session生命周期终止了,即不能操作一个未定义对象。
 
4.2总结
1, 用户注销web应用系统,最好的调用方式依次是 session_unset();  session_destroy();  unset($_SESSION);
2, 尽量将键与值填入$_SESSION,而不推荐使用session_register()。同样,尽量使用unset($_SESSION[‘var’]),而不使用session_unregister()。
3, 对于可能产生大量session的WEB应用,推荐使用的session.save_path的格式是session.save_path=”N:/path”。注意:这些目录需要手工创建,并且有httpd守护进程属主写权限。这样做可以获得更好的性能
4, 如果调用了session_regenerate_id()给用户分配了新的session id。该函数并不会主动删除旧的session文件,需要定时清理旧的session文件,这样更优化。
5, 尽量不要使用session_commit()提交sessioin数据,因为它同时会结束当前session,PHP默认会在页面生命周期的时候提交session数据到session文件
 
4.3 Session ID传递
     session终究是因为管理用户状态信息才存在的。我们曾探讨过session id的意义:每个来访问用户都会被分配一个唯一的session id,用于区分其它用户的session数据。换句话说,session id是用户表明身份的一种标识,就像入场券一样。用户一旦从被分配了session id之后的每次访问(http请求)都会携带这个session id给服务端,用于加载该用户的session数据。那么,通过什么方式传给服务端?这是我们这节探讨的内容。
     用户端与服务端的web通信协议是http。而PHP通过http取得用户数据惯用的三种方法分别是:POST方法、GET方法还有Cookie。而PHP默认传递方法正是Cookie,也是最佳方法。只有在客户端不支持Cookie的时候(浏览器禁用了Cookie功能)才会通过GET方法来传递session_id,即通过在URL的query_string部分传递session id。
     确定了传递方法,我们还有必要清楚一下session id的传递过程。用户通过浏览器访问网页,将URL输入地址栏回车,浏览器发出请求,在调用sockect send之前浏览器引擎会搜索有效的Cookies记录封装在http请求头的Cookie字段,一同发送出去。服务端器接收到请求后,交给PHP处理。这时,session初始化函数如果在$_COOKIE中没有找到以session_name()作为键值存储的生素(值为session id),则会以为用户是第一次访问web。作为第一次访问的用户,session初始化函数总会随机生成一个session_id并且通过setcookie()函数调用将新生成的session_id以”sesseson_name = session_id”的格式填入http响应头Set-Cookie字段,发送给客户端(这样接下来的请求,http请求头Cookie字段都会携带该Cookie记录给web服务器)。如果初始化函数发现用户端Cookies中已定义了存在$_COOKIE[‘sess_name’],则会加载与$_COOKIE[‘sess_name’]相对应的session文件($_COOKIE[‘sess_name’]就是session ID)。如果用户Cookie记录过期,则会被浏览器删除。之后的下一次请求,服务器会以为用户又是第一次访问,如此循环。
 
4.4 Session回收
通过上文几节介绍,我们知道session数据存放在服务端指定的session.save_path目录中,同时会在用户端存放一条Cookie用以记录分配给用户的session id。所以,session数据失效分服务端和客户端,要删除(回收)的对象也很清楚:
1,服务端:删除过期的session文件,启动PHP GC回收。
2,用户端:使存储了过期session_id的用户端Cookie记录过期。通过将Cookie的Expire设置为负值,要求客户端删除Cookie。
服务端:删除过期的session文件
      PHP GC进程被启动以后,则会扫描session.save_path,找出过期的session,并删除该session文件。所谓,过期的session,是指操作系统当前时间与session文件最后访问时间之差大于session.gc_maxlifetime的话,该session认为是过期了。注意:有时候,你会发现,即便是文件过期了,有可能也没有被及时地删除掉。这是因为,每次session初始化的时候,并不会都启动PHP GC进程的,启动GC进程会大大降低php的运行效率。所有一个启动概率,这个概率由php.ini设定session.gc_probability / session.gc_divisor二个设置决定,默认概率是1%(1/1000)。这意味着,每1000次用户请求中,会启动1次PHP GC回收session文件。
 
4.5 总结
1, PHP使用Cookie的方法传递session id。尽量不要使用GET方法传递session id,因为这样很不安全。
2, 可以通过setcookie()的方法,将客户端的session id的Cookie记录删除。
3, PHP GC进程由session初始化启动。但不是每一次用户请求都会被启动,它的启动概率默认是1/1000。过于频繁访问的网站,并发量大的网站,可减小PHP GC的启动频率。PHP GC回收session会降低php的执行效率。
参考:
1. http://blog.163.com/lgh_2002/blog/static/4401752620105246517509/

PHP会话控制的更多相关文章

  1. 会话控制:session与cookie

    我们在浏览网站时,访问的每一个web页面都需要使用"http协议"实现.而HTTP协议是无状态协议,就是说HTTP协议没有一个内建机制来维护两个事务之间的状态.当一个用户请求一个页 ...

  2. php 会话控制

    会话控制 HTTP协议,在TCP协议基础上的HTTP协议称为无状态协议 SESSION COOKIE SESSION特点:1.存储在服务器.2.每个使用者都会生成一个SESSION.3.有默认的过期时 ...

  3. (实用篇)php通过会话控制实现身份验证实例

    会话控制的思想就是指能够在网站中根据一个会话跟踪用户.这里整理了详细的代码,有需要的小伙伴可以参考下. 概述 http 协议是无状态的,对于每个请求,服务端无法区分用户.PHP 会话控制就是给了用户一 ...

  4. 会话控制:SESSION,COOKIE

    1.http协议: HTTP—超文本传输协议,在TCP协议(长连接.像一个硬件)基础上; 特点:短连接,无状态协议,没法记录本次连接的状态;适用于静态页面的访问,对于后期某些页面是需要浏览器预知客户信 ...

  5. PHP之自定义会话控制---使用文件处理

    前三篇简单的总结了下会话控制和文件操作,这一篇说说会话控制的自定义处理方式.既然知道了文件的基本读写,而且在会话控制中,也有人提到,session数据可以保存到缓存或数据库中,实际上当然不会是直接利用 ...

  6. PHP之会话控制小结

    会话控制是一种跟踪用户的通信方式,使用会话控制主要基于以下几点:由于http协议的无状态性,使得不能通过协议来建立两次请求之间的关联:对于通常的页面之间的数据传递方式get和post而言,主要处理参数 ...

  7. php——会话控制

    1.什么叫做会话控制 允许服务器根据客户端做出的连续请求. 2.为什么需要会话控制? 因为当你打开一个网站,并想访问该网站的其他页面的时候,如果没有会话控制,当跳转到其他页面的 时候,就需要再次输入账 ...

  8. PHP会话控制Session与Cookie

    理解会话控制的概念: 阅读过HTTP协议相关资料的同学都会知道HTTP协议是WEB服务器与客户端(浏览器)相互通信的协议,它是一种无状态协议,所谓无状态,指的是不会维护http请求数据,http请求是 ...

  9. (详细)php实现留言板---会话控制-----------2017-05-08

    要实现留言功能,发送者和接受者必不可少,其次就是留言时间留言内容. 要实现的功能: 1.登录者只能查看自己和所有人的信息,并能够给好友留言 2.留言板页面,好友采取下拉列表,当留言信息为空时,显示提示 ...

  10. PHP中的会话控制

    了解HTTP(超文本传输协议)可以知道,它采用请求与响应的模式,最大的特点就是无连接无状态. 无连接:每次连接仅处理一个客户端的请求,得到服务器响应后,连接就结束了 无状态:每个请求都是独立的,服务器 ...

随机推荐

  1. linux 下chown改变隐藏文件夹

    chown 在更改隐藏文件的时候,发现无法更改其用户组,如果需要将隐藏文件夹也做一个更改,那么需要加上-h选项. sudo  chown ai/node/  * -hR 使用以上命令即可.

  2. POJ:1222-EXTENDED LIGHTS OUT(矩阵反转)

    EXTENDED LIGHTS OUT Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12956 Accepted: 8186 ...

  3. 方法的重写(Override)与重载(Overload)的含义与区别

    1.Override(重写) 两同,两小,一大 两同:方法名相同,参数列表相同 两小:抛出的异常要小于等于父类,返回值类型要小于等于父类 一大:访问权限要大于等于父类 2.Overload(重载) 方 ...

  4. is 和 == 的区别,utf和gbk的转换,join用法

    is 和 == 的区别 # is 比较的是内存地址 # == 比较的是值 a = 'alex' b = 'alex' #int,str(小数据池)会被缓存,为了节约内存 print(id(a),id( ...

  5. 9.5web service基础知识

    Web服务基础 用户访问网站的基本流程 我们每天都会用web客户端上网,浏览器就是一个web客户端,例如谷歌浏览器,以及火狐浏览器等. 当我们输入www.oldboyedu.com/时候,很快就能看到 ...

  6. \r \r\n \t的区别

    \n 软回车:      在Windows 中表示换行且回到下一行的最开始位置.相当于Mac OS 里的 \r 的效果.      在Linux.unix 中只表示换行,但不会回到下一行的开始位置. ...

  7. Kafka安装和常用操作命令

    Kafka安装: 下载kafka_2.10-0.8.2.1 1.关闭防火墙 2.修改配置文件  server.properties broker.id=1log.dirs= /usr/kafka_2. ...

  8. 教你一步学会安装Hue

    一.简介 hue是一个开源的apache hadoop ui系统,由cloudear desktop演化而来,最后cloudera公司将其贡献给了apache基金会的hadoop社区,它基于pytho ...

  9. Reverse Word in a String(翻转字符串)&字符串最后一个单词的长度

    1.题目: Given an input string, reverse the string word by word. For example,Given s = "the sky is ...

  10. Android学习记录(4)—在java中学习多线程下载的基本原理和基本用法①

    多线程下载在我们生活中非常常见,比如迅雷就是我们常用的多线程的下载工具,当然还有断点续传,断点续传我们在下一节来讲,android手机端下载文件时也可以用多线程下载,我们这里是在java中写一个测试, ...