会话控制Session的应用

  Session技术与Cookie相似,都是用来存储使用者的相关资料。但是最大不同之处在于Cookie是将数据存放于客户端计算机中,而Session则是将数据存放于服务器系统下。

  在Web技术发展史上,虽然Cookie技术的出现是一个重大的变革,但Cookie是在客户端计算机中保存资料,所以引起了一个争议。用户有权阻止Cookie的使用,使Web服务器无法通过Cookie来跟踪用户信息。而Session技术是将使用者相关的资料存放在服务器的系统之下,所以使用者无法停止Session的使用。

  可以把Cookie比喻成第一次去商场时为你提供的会员卡,并有用户自己保存。如果用户下次再去商场购物时忘记带卡了,或者是把卡弄丢了,这样用户就不能再以会员的身份购物了。但是如果商场在为用户办理会员卡以后,再由商场保存这张卡,用户就不用每天都把卡放在身上了。但是商场的会员特别多,你每次来时,商场怎么知道你是这里的会员呢?所以在用户办理会员卡时,商场会要求用户保存会员卡的卡号。下次这个用户再来购物时,商场就可以通过用户提供的卡号查询到会员的登记信息。

  Session就是这样,在客户端仅需要保存由服务器为用户创建的一个Session标识符(相当于会员卡卡号),称为Session ID,而在服务器端(文件/数据库/Memcache中)保存Session变量的值。Session ID是一个既不会重复,又不容易找到规律的,由32位十六进制数组成的字符串。Session ID会被保存在客户端的Cookie里,如果用户阻止Cookie的使用,则可以将Session ID保存在用户浏览器地址栏的URL中。当用户请求Web服务器时,就会把Session ID发送给服务器,再通过Session ID提取保存在服务器中的Session变量。可以把Session中保存的变量,当做是这个用户的全局变量,同一个用户对每个脚本的访问都共享这些变量。

  当某个用户想Web服务器发送请求时,服务器首先检查这个客户端的请求是否已经包含了一个Session ID。如果包含,说明之前已经为此用户创建国Session ID,服务器则按该Session ID把Session检索出来使用。如果客户端请求不包含Session ID,则为该用户创建一个Session,并且生成一个与此Session关联的Session ID,在本次相应中被传送给客户端保存。

配置SESSION

  在PHP配置文件中,有一组和Session相关的配置选项。通过对一些选项重新设置新值,就可以对Session进行配置,否则使用默认的Session配置。在php.ini文件中和Session有关的,一些有意义选项及其描述如下表所示。

选项名 描述 默认值
session.auto_start 在客户访问任何页面时自动开启并初始化Session,默认禁止(因为类定义必须在会话之前被载入,所以若打开这个选项,你就不能在会话中存放对象) 禁用(0)
session.cookie_domain 传递会话ID的Cookie作用域(默认为空时会根据Cookie规范去自动生成主机名) none
session.cookie_lifetime Cookie中Session ID在客户机上保存的有效期(秒),0表示延续到浏览器关闭时 0
session.cookie_path 传递会话ID的Cookie作用路径 /
session.name 会话的名称,用在客户端Cookie里会话ID标识名,只能包含字母和数字 PHPSESSID
session.save_path 对于files处理器,此值是创建会话数据文件的路径 /tmp
session.use_cookies 是否使用Cookie在客户端保存会话ID,1表示允许 1
session.use_trans_sid 是否使用明码在URL中显示SID(会话ID)。(基于URL的会话管理总是比基于Cookie的会话管理有更多的风险,所以应当禁用) 默认禁止(false)
session.gc_probability

定义在每次初始化会话时,启动垃圾回收程序的概率,这个概率计算公式如下:

session.gc_probability/session.gc_divisor

对会话页面访问频繁,概率就越小。建议值为1/1000~5000

1/1000
session.gc_divisor
session.gc_maxlifetime 超过此参数所指的秒数后,保存的数据将被视为‘垃圾’并由垃圾回收程序清理 1440(24分钟)
session.save_handler 存储和检索与会话关联的数据的处理器名字,可以使用(files、user、sqlite、memcache)中的一个值,默认为文件(files),如果想要使用自定义的处理器(如基于数据库或者Memcache的处理器),可用“user” files

Session的声明与使用

  Session的设置不同于Cookie,必须先启动,在PHP中必须调用session_start()函数,以便让PHP核心程序,将和Session相关的内建环境变量预先载入至内存中。

  bool session_start(void)

  这个函数没有参数,且返回值均为TRUE。有两个主要作用,一是开始一个会话,二是返回已经存在的会话。

  当第一次访问网站时,session_start()函数就会创建一个唯一的Session ID,并自动通过HTTP的响应头,将这个Session ID保存在客户端Cookie中。同时,也在服务器端创建一个以这个Session ID命名的文件,用于保存这个用户的会话信息。当同一个用户再次访问这个网站时,也会自动通过HTTP的请求头将客户端Cookie中保存的Session ID再携带过来,这时session_start()函数就不会再去分配一个新的Session ID,而是在服务器的硬盘上去寻找和这个Session ID同名的Session文件,将之前为这个用户保存的会话信息读出,在当前脚本应用达到跟踪这个用户的目的。所以在会话期间,同一个用户在访问服务器上的任何页面时,都是同一个Session ID。

  如果你是使用基于Cookie的Session,在使用该函数开启Session之前,不能有任何输出的内容。因为基于Cookie的Session是在开启的时候,调用session_start()函数会生成一个唯一的Session ID,需要保存在客户端计算机的Cookie中,和setcookie()函数一样,有头信息的设置过程,所以在调用之前不能有任何的输出,空格或空行也不行。

  如果不想在每个脚本都使用session_start()函数开启Session,可以在php.ini里设置“session.auto_start=1”,则无须每次使用Session之前调用session_start()函数。但启用该选项也有一些限制,即不能将对象放入Session中,因为类定义必须在启动Session之前加载。所以不建立使用php.ini的session.auto_start属性来开启Session。

注册一个会话变量和读取Session

  在PHP中使用Session变量,除了必须要启动之外,还要经过注册的过程。注册和读取Session变量,都要通过访问 $_SESSION数组完成。但必须在调用session_start()函数开启Session之后才能使用。$_SESSION总是具有全局范围,因此不需要对$_SESSION使用global关键字。

session_start();
$_SESSION['username'] = "skygao";
$_SESSION['uid'] = 1;

  执行该脚本后,两个Session变量就会被保存在服务器端的某个文件中,该文件的位置是通过php.ini文件,在session.save_path属性执行的目录下,为这个访问的用户单独创建的文件,用来保存注册的Session值。例如,某个保存Session变量的文件名为“sess_1uebcnr0cd3ocbjg36s8ep0105”,文件名中含Session ID,所以每个访问用户在服务器都有自己的保存Session变量的文件。该文件的内容结构如下所示:

  变量名|类型:长度:值;

  本例在Session中注册了两个变量,如果在服务器找中找到为该用户保存Session变量的文件,打开后可以看到如下内容:

username|s:6:"skygao";uid|i:1;

注销变量与销毁Session

  当使用完一个Session变量后,可以将其删除,当完成一个会话后,也可以将其销毁。销毁和当前Session有关的所有资料,可以调用session_destroy()函数结束当前的会话,并清空会话中所有资源。

  bool session_destroy(void)

  相对于session_start()函数(创建Session文件),该函数用来关闭Session的运作(删除Session文件),如果成功则传回TRUE,销毁Session资料失败则返回false。但该函数并不会释放和当前Session相关的变量,也不会删除保存在客户端Cookie中的Session ID。因为$_SESSION数组和自定义的数组在使用上是相同的,所以我们可以使用unset()函数来释放Session中注册的单个变量。

unset($_SESSION['username']);
unset($_SESSION['uid']);

  一定要注意,不要使用unset($_SESSION)删除整个$_SESSION数组,这样将不能再通过$_SESSION超全局数组注册变量。但如果想把某个用户在Session中注册的所有变量都删除,可以直接将数组变量$_SESSION赋上一个空数组。

$_SESSION = array();

  PHP默认的Session是基于Cookie的,Session ID被服务器存储在客户端的Cookie中,所以销毁Session时也要清除Cookie中保存的Session ID,而这就必须借助setcookie()函数完成。在Cookie中,保存Session ID的Cookie标示名称就是Session的名称,这个名称是php.ini中,通过session.name属性指定的值。在PHP脚本中,可以通过调用session_name()函数获取Session名称。删除保存在客户端Cookie中的Session ID,代码如下:

if(isset($_COOKIE[session_name()])){
setcookie(session_name(),'',time() - 3600,'/');
}

  通过前面的介绍可以总结出,Session的注销过程共需要4个步骤,在下例中,提供完整的4个步骤代码,运行该脚本就可以关闭Session,并销毁与本次会话相关的所有资源,代码如下所示:

session_start();
//第一步:开启Session并初始化 $_SESSION = array();
//第二步:删除所有Session变量,也可以用unset($_SESSION[xxx])逐个删除 if(isset($_COOKIE[session_name()])){
setcookie(session_name(),'',time() - 3600 ,'/');
}
//第三步:如果使用基于Cookie的Session,使用setcookie()删除包含SESSION ID的Cookie session_destroy();
//第四步:最后彻底销毁Session

  使用“$_SESSION = array();”清空$_SESSION数组的同时,也将这个用户在服务器端对应的Session文件内容清空,而使用session_destroy()时,则是将这个用户在服务器端对应的Session文件删除。

上一篇:PHP......会话控制SESSION与COOKIE


下一篇:Swift - 绘制背景线条