跳转到内容

PHP 编程/会话

来自维基教科书,开放的书,开放的世界

会话允许 PHP 脚本在 Web 服务器上存储数据,这些数据可以在以后使用,即使在对不同 PHP 页面请求之间也是如此。每个会话都有一个不同的标识符,它作为 cookie 或 $_GET 变量发送到客户端的浏览器。会话在用户关闭浏览器时、Web 服务器删除会话信息时或程序员显式销毁会话时结束。在 PHP 中,它通常称为 PHPSESSID。会话对于保护用户无法读取或写入的数据非常有用,尤其是在 PHP 开发人员不希望在 cookie 中提供信息的情况下,因为它们很容易被读取。会话可以通过 $_SESSION 超全局变量来控制。存储在此数组中的数据在整个会话期间保持持久性。它是一个简单的数组。会话比 cookie 更易于使用,这为 PHP 开发人员提供了很大帮助。通常,会话用于用户登录、购物车和其他需要保持浏览流畅的补充。PHP 脚本可以轻松控制正在发送的会话 cookie,并控制整个会话数据。会话始终存储在一个唯一的文件名中,要么在临时文件夹中,要么在特定文件夹中,如果脚本指示这样做。

使用会话

[编辑 | 编辑源代码]

在每个将成为当前会话一部分的 PHP 脚本的顶部,必须使用 session_start() 函数。它必须在第一个输出(echo 或其他)之前,否则会导致错误“Headers already sent out”。

 session_start();

此函数将执行以下操作

  1. 它将检查 _COOKIE_GET 数据,如果已给出
  2. 如果会话文件在 session.save_path 位置不存在,它将
    1. 生成一个新的唯一标识符,并且
    2. 基于该标识符创建一个新文件,并且
    3. 将一个 cookie 发送到客户端的浏览器
  3. 如果它确实存在,PHP 脚本将尝试将文件的数据存储到 _SESSION 变量中,以供进一步使用

现在,您可以通过两种不同的方式简单地设置变量,默认方法

 $_SESSION['example'] = "Test";

或过时的使用方法

 $example="Test";
 session_register($example);

以上两个语句都将注册会话变量 $_SESSION['example'] 作为“Test”。过时的使用方法不应使用,仅列出是因为您仍然可以在由不知道新方法的程序员编写的脚本中看到它。建议使用默认方法。

会话配置选项

[编辑 | 编辑源代码]

PHP 会话很容易控制,并且可以通过一些小的因素变得更加安全或不太安全。以下是一些可以使用 php_ini() 函数轻松更改的运行时选项

名称 默认值 可更改
session.save_path "/tmp" PHP_INI_ALL
session.name "PHPSESSID" PHP_INI_ALL
session.save_handler "files" PHP_INI_ALL
session.auto_start "0" PHP_INI_ALL
session.gc_probability "1" PHP_INI_ALL
session.gc_divisor "100" PHP_INI_ALL
session.gc_maxlifetime "1440" PHP_INI_ALL
session.serialize_handler "php" PHP_INI_ALL
session.cookie_lifetime "0" PHP_INI_ALL
session.cookie_path "/" PHP_INI_ALL
session.cookie_domain "" PHP_INI_ALL
session.cookie_secure "" PHP_INI_ALL
session.use_cookies "1" PHP_INI_ALL
session.use_only_cookies "0" PHP_INI_ALL
session.referer_check "" PHP_INI_ALL
session.entropy_file "" PHP_INI_ALL
session.entropy_length "0" PHP_INI_ALL
session.cache_limiter "nocache" PHP_INI_ALL
session.cache_expire "180" PHP_INI_ALL
session.use_trans_sid "0" PHP_INI_SYSTEM/PHP_INI_PERDIR
session.bug_compat_42 "1" PHP_INI_ALL
session.bug_compat_warn "1" PHP_INI_ALL
session.hash_function "0" PHP_INI_ALL
session.hash_bits_per_character "4" PHP_INI_ALL
url_rewriter.tags "a=href,area=href,frame=src,input=src,form=fakeentry" PHP_INI_ALL

这段代码就是一个简单的例子

 //Setting The Session Saving path to "sessions", '''must be protected from reading'''
 session_save_path("sessions"); // This function is an alternative to ini_set("session.save_path","sessions");
 //Session Cookie's Lifetime ( not effective, but use! )
 ini_set("session.cookie_lifetime",time()+60*60*24*500);
 //Change the Session Name from PHPSESSID to SessionID
 session_name("SessionID");
 //Start The session
 session_start();
 //Set a session cookie ( Required for some browsers, as settings that had been done before are not very effective 
 setcookie(session_name(), session_id(), time()+3600*24*365, "/");

此示例只是将 cookie 设置为下一年。

结束会话

[编辑 | 编辑源代码]

当用户单击“注销”或“退出”时,您通常希望销毁所有登录数据,以便任何人都无法再访问它。会话文件将被简单地删除,并且 cookie 将被取消设置

 session_destroy();

使用其他类型会话数据

[编辑 | 编辑源代码]

诸如整数、字符串和数组之类的简单数据可以轻松地存储在 $_SESSION 超全局数组中,并从一个页面传递到另一个页面。但在尝试通过赋值存储对象的状

避免会话固定

[编辑 | 编辑源代码]

会话固定描述了一种攻击向量,其中恶意第三方设置(即固定)用户的会话标识符 (SID),因此能够访问该用户的会话。在如上所述的会话的基本实现中,这

  1. 不要使用 GET 或 POST 变量来存储会话 ID(在大多数 PHP 配置中,cookie 用于存储 SID,因此程序员不需要执行任何操作来实现此功能);
  2. 在每次用户请求时重新生成 SID(在会话开始时使用 session_regenerate_id());
  3. 使用会话超时:对于每个用户请求,存储当前时间戳,并在下次请求时检查是否已超过超时间隔;
  4. 提供注销功能;
  5. 在每次请求时检查“浏览器指纹”。这是一个存储在 $_SESSION 变量中的哈希,包含用户代理标头、客户端 IP 地址、盐值和/或其他信息的组合。有关此
  6. 检查来源:这并不适用于所有系统,但如果您知道您网站的用户必须来自某个已知域,那么您可以丢弃与来自其他地方的用户相关的会话。它依赖于用户代理提
此示例代码解决了上述所有要点,除了来源检查。
$timeout = 3 * 60; // 3 minutes
$fingerprint = md5('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT']);
session_start();
if ( (isset($_SESSION['last_active']) && (time() > ($_SESSION['last_active']+$timeout)))
     || (isset($_SESSION['fingerprint']) && $_SESSION['fingerprint']!=$fingerprint)
     || isset($_GET['logout']) ) {
    do_logout();
}
session_regenerate_id(); 
$_SESSION['last_active'] = time();
$_SESSION['fingerprint'] = $fingerprint;
do_logout() 函数销毁会话数据并取消设置会话 cookie。


华夏公益教科书