PHP Session

PHP session 变量用于存储关于 session(用户会话)的信息,或者更改 session(用户会话)的设置。session 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的。

在计算机上操作某个应用程序时,打开它,做些更改,然后关闭它,这很像一次对话(session)。计算机能够清楚记录操作人,打开和关闭应用程序的时间。然而,在因特网上问题出现了:由于 HTTP 地址无法保持状态,Web 服务器并不知道你是谁以及你做了什么。PHP session 解决了这个问题,它通过在服务器上存储用户信息以便随后使用(比如用户名称、购买商品等)。然而,会话信息是临时的,在用户离开网站后将被删除。如果需要永久存储信息,可以把数据存储在数据库中。

session 的工作机制是:为每个访客创建一个唯一的 id (UID),并基于这个 UID 来存储变量。UID 存储在 cookie 中,或者通过 URL 进行传导。

启动 session

session 的设置不同于 cookie,必须先启动,在PHP中必须调用 session_start()。

					
/*
 * 创建 session,开始一个会话,进行 session 初始化。
 * session_start() 函数之前不能有任何输出,必须位于 <html> 标签之前。
 */
Bool session_start(void)
					
				
					
/*
 * 向服务器注册用户的会话 session,以便可以开始保存用户信息,同时会为用户会话分配一个 UID。
 */
<?php session_start(); ?>

<html>

</html>
					
				

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

存取 session

通过 $_SESSION 变量(数组)来存取 session 变量。

					
<?php
  //启动 session
  session_start();
  //存储 session 
  $_SESSION['username'] = 'wanghao';
 ?>

<html>
  <head>
  </head>
  <body>
    <?php
      echo "用户".$_SESSION['username']."您好!";
     ?>
  <body>  
</html>
					
				

说明:

创建了一个简单的 page-view 计数器。isset() 函数检测是否已设置 "views" 变量。如果已设置 "views" 变量,我们累加计数器。如果 "views" 不存在,则创建 "views" 变量,并把它设置为 1。

					
		<?php
		  session_start();
		  
		  if(isset($_SESSION['views'])) {
		    $_SESSION['views']++;
		  } else {
		    $_SESSION['views'] = 1;
		  }

		  echo "浏览量:".$_SESSION['views'];
		 ?>
					
				

删除 session

使用 unset() 或 session_destroy() 函数删除某些 session 数据。

当使用完一个 session 变量后,可以将其删除(删除某个变量),当完成一个会话后,也可以将其销毁(删除整个文件)。如果用户退出 Web 系统,就需要为他提供一个注销的功能,把他的所有信息在服务器中销毁。销毁和当前 session 有关的所有资料,可以调用 session_destroy() 函数结束当前的会话,并清空会话中的所有资源。

					
/*
 * 销毁和当前 session 有关的所有资料(session 变量文件)。
 */
bool session_destroy(void)
					
				

session_destroy() 函数并不会释放和当前 session 相关的变量,也不会删除保存在客户端 cookie 中的 sessionID。

					
<?php
  session_start();
  $_SESSION['name'] = 'wanghao';
  session_destroy();
  echo $_SESSION['name'];     //仍然可以输出'wanghao'
 ?>
					
				

因为 $_SESSION 数组和自定义的数组在使用上是相同的。可以使用 unset() 函数来释放在 session 中注册的单个变量。

					
/*
 * unset() 函数用于释放指定的 session 变量。
 */
<?php
  session_start();
  $_SESSION['name'] = 'wanghao';
  session_destroy();
  echo $_SESSION['name'];     //仍然可以输出'wanghao'
  unset($_SESSION['name']);
  echo $_SESSION['name'];     //Undefined index: name
 ?>
					
				

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

					
$_SESSION = array();
					
				

PHP 默认的 session 是基于 cookie 的,sessionID 被服务器存储在客户端的 cookie 中。

所以在注销 session 时也需要清除 cookie 中保存的 sessionID,而这就必须借助 setCookie() 函数完成。在 PHP 脚本中,可以通过调用session_name()函数获取Session名称。删除保存在客户端Cookie中的SessionID,所以,如果客户端禁止了 cookie 的话,那么 session 也就没有办法使用。

关于验证登陆用户是否有 admin 权限的例子

如果用户成功登陆的话,储存一个登陆成功的凭证的 session,即 admin = true。

					
		<?php
		  //表单提交后...
		  $posts = $_POST;
		  //清除一些空白符号
		  foreach ($posts as $key => $value) {
		    $posts[$key] = trim($value);
		  }
		  $password = md5($posts["password"]);
		  $username = $posts["username"]; 
		  $query = "SELECT `username` FROM `user` WHERE `password` = '$password' AND `username` = '$username'";
		  //取得查询结果
		  $userInfo = $DB->getRow($query); 

		  if (!empty($userInfo)) {
		    //当验证通过后,启动 Se
		  index.html

		> 验证 session里的`admin`是否为 `true`

		<?php
		  //防止全局变量造成安全隐患
		  $admin = false;
		  //  启动会话,这步必不可少
		session_start();
		//  判断是否登陆
		if (isset($_SESSION["admin"]) && $_SESSION["admin"] === true) {
		    echo "您已经成功登陆";
		} else {
		    //  验证失败,将 $_SESSION["admin"] 置为 false
		    $_SESSION["admin"] = false;
		    die("您无权访问");
		}
		?>
					
				

Session 函数

https://www.php.net/manual/zh/ref.session.php

session_abort

session_cache_expire

session_id

获取/设置当前会话 ID。

					
/*
 * session_id() 可以用来获取/设置当前会话 ID。
 * 为了能够将会话 ID 很方便的附加到 URL 之后,可以使用常量 SID 获取以字符串格式表达的会话名称和 ID。
 *    string $id: 如果指定了 id 参数的值, 则使用指定值作为会话 ID。
 * return string: session_id() 返回当前会话 ID。 如果当前没有会话,则返回空字符串("")。
 */
session_id ([ string $id ] ) : string
					
				
					
<?php
  session_start();
  $_SESSION['name'] = 'wanghao';
  echo session_id();                   //dufg0vcepkgo47ktcmin14skq1
  echo session_id($_SESSION['name']);  //创建 sess_wanghao 文件
 ?>
					
				

session_is_registered

检查变量是否在会话中已经注册。

session_name

读取/设置会话名称。

					
/*
 * session_id() 可以用来获取/设置当前会话 ID。
 * 为了能够将会话 ID 很方便的附加到 URL 之后,可以使用常量 SID 获取以字符串格式表达的会话名称和 ID。
 *  string $name: 如果指定 name 参数, session_name() 函数会更新会话名称,并返回原来的会话名称。。
 * return string: session_name() 函数返回当前会话名称。
 */
session_name ([ string $name ] ) : string
					
				
					
<?php 
  session_start();
  $_SESSION['name'] = 'wanghao';
  echo session_name()."<br>";           //PHPSESSID
  echo $_COOKIE[session_name()];        //dufg0vcepkgo47ktcmin14skq1
 ?>
					
				

请求开始的时候,会话名称会被重置并且存储到 session.name 配置项。 因此,要想设置会话名称,那么对于每个请求,都需要在调用 session_start() 函数之前调用 session_name() 函数。

Session 文件异常

wamp 加载的 php.ini 在 apache 目录中。

php.ini 设置问题

					
/*
 * 常规 session
 */
session.auto_start = 0
//php 文件中使用:
session_start();

/*
 * 自动开启 session
 */
session.auto_start = 1
					
				

同时生成2个 session 文件,其中一个是 0 kb

重新设置 session.save_path,设置完成以后重启 iis/wamp 看是否成功。 如果不成功,设置两个 session.save_path ,因为在 php.ini 中为了兼容以前的版本是有两个的:一个是被注释掉的,一个是 4.0 以上,一个是 5.0 以上的。设置完成后,设置目录为 everyone 读取 写入,然后继承,其他的都不要勾取,这样就保证了保存目录的安全和系统数据的安全。