当前位置: 首页 > news >正文

从0到1学PHP(九):PHP 会话管理:跟踪用户状态

目录

  • 一、Cookie 的使用
    • 1.1 Cookie 的原理及设置方法(setcookie () 函数)
    • 1.2 Cookie 的读取、修改和删除
    • 1.3 Cookie 的应用场景及限制
  • 二、Session 的使用
    • 2.1 Session 的工作原理及开启方法(session_start ())
    • 2.2 Session 变量的设置、读取和销毁
    • 2.3 Session 的配置与安全考虑
  • 三、登录与注销功能实现
    • 3.1 基于 Session 的用户登录验证流程
    • 3.2 安全的注销机制及记住登录状态功能


一、Cookie 的使用

1.1 Cookie 的原理及设置方法(setcookie () 函数)

Cookie 是一种在客户端(通常是浏览器)存储数据的机制,它允许服务器将少量数据存储在用户的浏览器中,这些数据会在后续的请求中被发送回服务器,从而实现对用户状态的跟踪 。其原理是,当用户首次访问网站时,服务器通过 HTTP 响应头中的Set-Cookie字段向浏览器发送 Cookie。例如,服务器发送Set-Cookie: username=John; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/;,浏览器会将这个 Cookie 保存下来。之后,每当浏览器向该服务器发送请求时,都会在请求头中带上这个 Cookie,如Cookie: username=John ,这样服务器就能识别用户身份或获取相关信息。

在 PHP 中,使用setcookie()函数来设置 Cookie。该函数的语法如下:

bool setcookie ( string $name [, string $value = "" [, int $expire = 0 [, string $path = "" [, string $domain = "" [, bool $secure = false [, bool $httponly = false ]]]]]] )
  • $name :Cookie 的名称,这是必需参数,例如username。
  • $value :Cookie 的值,可选参数,默认值为空字符串,如John。
  • $expire :Cookie 的过期时间,以 Unix 时间戳表示。如果设置为 0(默认值),则 Cookie 在浏览器关闭时过期;如果设置为一个未来的时间戳,例如time() + 3600(表示当前时间加上 3600 秒,即 1 小时后过期) ,则 Cookie 会在指定时间过期。
  • $path :Cookie 的有效路径。如果设置为/,则整个网站都可以访问该 Cookie;如果设置为/admin/,则只有/admin/目录及其子目录下的页面可以访问该 Cookie。
  • $domain :Cookie 的有效域名。例如example.com,则该域名及其所有子域名(如sub.example.com)都可以访问该 Cookie。
  • $secure :如果设置为true,则 Cookie 仅在 HTTPS 连接下才会被发送,以提高安全性。
  • $httponly :如果设置为true,则 Cookie 只能通过 HTTP 协议访问,无法通过 JavaScript 等脚本语言访问,这样可以防止跨站脚本攻击(XSS)窃取 Cookie。

下面是一个设置 Cookie 的示例:

<?php
// 设置一个名为username,值为John,1小时后过期,对整个网站有效的Cookie
setcookie('username', 'John', time() + 3600, '/');
?>

1.2 Cookie 的读取、修改和删除

读取 Cookie 非常简单,PHP 通过$_COOKIE超全局数组来访问已设置的 Cookie。例如,要读取前面设置的username Cookie,可以这样做:

<?php
if (isset($_COOKIE['username'])) {echo "Welcome, " . $_COOKIE['username'];
}
?>

修改 Cookie 时,只需要再次调用setcookie()函数,使用相同的$name参数,并更新其他参数(如$value、$expire等) 。例如,要将username Cookie 的值修改为Jane,并将过期时间延长到 2 小时后:

<?php
setcookie('username', 'Jane', time() + 7200, '/');
?>

删除 Cookie 的方法是设置一个过去的过期时间。例如,要删除username Cookie:

<?php
setcookie('username', '', time() - 3600, '/');
?>

1.3 Cookie 的应用场景及限制

Cookie 在 Web 开发中有许多应用场景:

  • 会话管理:存储用户的登录状态,如保存session_id,这样用户在浏览网站的不同页面时,服务器可以识别用户身份,无需重复登录。
  • 个性化设置:记录用户的偏好,比如用户选择的语言、主题等,下次用户访问时可以直接应用这些设置,提升用户体验。例如,一个新闻网站可以使用 Cookie 记录用户喜欢的新闻类别,为用户推荐相关内容。
  • 购物车功能:在电商网站中,Cookie 可以用来存储用户购物车中的商品信息,即使用户关闭浏览器再重新打开,购物车内容依然存在。

然而,Cookie 也有一些限制:

  • 大小限制:单个 Cookie 的大小通常限制在 4KB 左右,这意味着不能在 Cookie 中存储大量数据。如果需要存储更多数据,应考虑其他存储方式,如localStorage(客户端存储)或数据库(服务端存储)。
  • 安全风险:由于 Cookie 存储在客户端,容易被窃取或篡改。虽然可以通过设置secure和httponly标志来增强安全性,但敏感信息(如密码)不应该存储在 Cookie 中。secure标志确保 Cookie 仅通过 HTTPS 连接传输,防止在 HTTP 连接中被截获;httponly标志防止 JavaScript 访问 Cookie,降低跨站脚本攻击的风险。
  • 浏览器限制:不同浏览器对 Cookie 的数量和大小限制可能略有不同,而且用户可以手动禁用浏览器的 Cookie 功能,这可能会影响依赖 Cookie 的功能正常运行。

二、Session 的使用

2.1 Session 的工作原理及开启方法(session_start ())

Session 是一种服务器端的存储机制,用于在用户与服务器之间传递数据,跟踪用户的状态 。其工作原理如下:当用户首次访问网站时,服务器会为该用户生成一个唯一的 Session ID,这个 ID 是一个字符串,例如5e9f8c8d2a4f4e889a2d8b8c7f999c88 。服务器将这个 Session ID 保存在浏览器的 Cookie 中(默认名为PHPSESSID) ,同时在服务器端创建一个与该 Session ID 关联的存储区域,可以是内存、文件系统或数据库 。之后,用户的每一次请求都会将这个 Session ID 通过 Cookie 发送回服务器,服务器根据接收到的 Session ID 查找对应的存储区域,获取和更新用户的会话数据,从而实现对用户状态的跟踪。

在 PHP 中,使用session_start()函数来启动一个会话。该函数必须在任何 HTML 输出之前调用,因为它会向浏览器发送 HTTP 头信息来传递 Session ID 等信息,如果在输出内容之后调用,PHP 会报错。示例代码如下:

<?php
session_start();
?>
<!DOCTYPE html>
<html>
<head><title>Session Example</title>
</head>
<body><!-- 页面内容 -->
</body>
</html>

2.2 Session 变量的设置、读取和销毁

设置 Session 变量非常简单,通过$_SESSION超全局数组来操作。$_SESSION是一个关联数组,使用键值对的形式存储数据。例如,要设置用户的登录状态和用户名:

<?php
session_start();
// 设置Session变量
$_SESSION['is_logged_in'] = true;
$_SESSION['username'] = 'John';
?>

读取 Session 变量同样通过$_SESSION数组,如下所示:

<?php
session_start();
// 读取Session变量
if (isset($_SESSION['is_logged_in']) && $_SESSION['is_logged_in']) {echo "Welcome, " . $_SESSION['username'];
}
?>

销毁 Session 变量有多种方式:

  • 删除单个 Session 变量:使用unset()函数,例如删除username变量:
<?php
session_start();
unset($_SESSION['username']);
?>
  • 删除所有 Session 变量:可以将一个空数组赋值给$_SESSION,或者使用session_unset()函数。使用空数组赋值:
<?php
session_start();
$_SESSION = array();
?>

使用session_unset()函数:

<?php
session_start();
session_unset();
?>
  • 销毁整个 Session:使用session_destroy()函数,它会销毁服务器上与当前 Session ID 关联的所有数据,但不会删除浏览器中的 Session ID Cookie。要完全销毁 Session,通常还需要手动清除$_SESSION数组,并设置一个过去的时间来删除 Session ID Cookie。示例如下:
<?php
session_start();
// 销毁Session
session_destroy();
// 清除$_SESSION数组
$_SESSION = array();
// 删除Session ID Cookie
if (isset($_COOKIE[session_name()])) {setcookie(session_name(), '', time() - 3600, '/');
}
?>

2.3 Session 的配置与安全考虑

在 PHP 中,可以通过session_set_cookie_params()函数来配置 Session 的 Cookie 参数,例如设置 Session ID Cookie 的有效期、路径、域名、安全标志和httponly标志等 。函数语法如下:

bool session_set_cookie_params ( int $lifetime [, string $path [, string $domain [, bool $secure = false [, bool $httponly = false ]]]] )
  • $lifetime :Session ID Cookie 的有效期,以秒为单位。如果设置为 0(默认值),则 Cookie 在浏览器关闭时过期;如果设置为一个正数,例如3600,则 Cookie 会在 3600 秒(1 小时)后过期。
  • $path :Session ID Cookie 的有效路径。如果设置为/,则整个网站都可以访问该 Cookie;如果设置为/admin/,则只有/admin/目录及其子目录下的页面可以访问该 Cookie。
  • $domain :Session ID Cookie 的有效域名。例如example.com,则该域名及其所有子域名(如sub.example.com)都可以访问该 Cookie。
  • $secure :如果设置为true,则 Session ID Cookie 仅在 HTTPS 连接下才会被发送,以提高安全性,防止在 HTTP 连接中被截获。
  • $httponly :如果设置为true,则 Session ID Cookie 只能通过 HTTP 协议访问,无法通过 JavaScript 等脚本语言访问,这样可以防止跨站脚本攻击(XSS)窃取 Session ID。

安全考虑方面,Session 面临一些安全风险,需要采取相应措施:

  • 会话劫持:攻击者可能通过窃取 Session ID 来劫持用户会话。防范方法包括:
    • 使用 HTTPS:通过加密通信,防止 Session ID 在传输过程中被窃取。在session_set_cookie_params()中设置$secure = true,确保 Session ID Cookie 仅在 HTTPS 连接下传输。
    • 设置 httponly:在session_set_cookie_params()中设置$httponly = true,防止 JavaScript 访问 Session ID Cookie,降低 XSS 攻击窃取 Session ID 的风险。
    • 定期更换 Session ID:使用session_regenerate_id()函数定期生成新的 Session ID,减少 Session ID 被破解的可能性。例如,在用户登录成功后,或者在关键操作前调用该函数:
<?php
session_start();
session_regenerate_id();
?>
  • 会话固定攻击:攻击者预先知道一个有效的 Session ID,然后诱使用户使用该 ID 进行登录,从而获取用户权限。防范方法是在用户登录成功后,立即生成新的 Session ID,覆盖原来的 ID,同样使用session_regenerate_id()函数。
  • Session 数据泄露:由于 Session 数据存储在服务器端,如果服务器被攻击,可能导致 Session 数据泄露。因此要确保服务器的安全性,及时更新服务器软件和应用程序,防止漏洞被利用;同时,不要在 Session 中存储过于敏感的数据,如用户密码等。

三、登录与注销功能实现

3.1 基于 Session 的用户登录验证流程

  1. 用户提交登录表单:用户在登录页面输入用户名和密码,然后点击登录按钮,此时浏览器会将包含用户名和密码的表单数据通过 HTTP 请求(通常是 POST 请求)发送到服务器。例如,以下是一个简单的 HTML 登录表单:
<!DOCTYPE html>
<html>
<head><title>Login</title>
</head>
<body><form action="login.php" method="post"><label for="username">Username:</label><input type="text" id="username" name="username" required><br><br><label for="password">Password:</label><input type="password" id="password" name="password" required><br><br><input type="submit" value="Login"></form>
</body>
</html>
  1. 服务器接收并验证数据:服务器端的 PHP 脚本(如login.php)接收表单数据,通过$_POST超全局数组获取用户名和密码。然后,脚本会连接数据库,查询数据库中是否存在匹配的用户名和密码记录。例如:
<?php
session_start();
// 获取表单数据
$username = $_POST['username'];
$password = $_POST['password'];// 连接数据库
$conn = mysqli_connect("localhost", "username", "password", "database_name");
if (!$conn) {die("Connection failed: ". mysqli_connect_error());
}// 查询数据库验证用户
$query = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
$result = mysqli_query($conn, $query);if (mysqli_num_rows($result) == 1) {// 验证成功// 创建Session变量$_SESSION['is_logged_in'] = true;$_SESSION['username'] = $username;// 重定向到用户主页header("Location: home.php");
} else {// 验证失败$error = "Invalid username or password";
}mysqli_close($conn);
?>
  1. 创建 Session 并记录用户状态:如果用户名和密码验证成功,服务器会创建 Session 变量来记录用户的登录状态和相关信息,如用户名。通过$_SESSION超全局数组设置这些变量,如上述代码中$_SESSION[‘is_logged_in’] = true;和$_SESSION[‘username’] = $username; 。然后,服务器会将用户重定向到其主页或其他受保护的页面。
  2. 后续请求验证:在用户访问受保护的页面时,页面的 PHP 脚本首先会调用session_start()函数启动会话,然后检查$_SESSION中是否存在表示用户已登录的变量,如$_SESSION[‘is_logged_in’] 。如果存在且值为true,则说明用户已登录,可以访问该页面;否则,用户会被重定向到登录页面或显示错误信息。例如,在home.php页面中:
<?php
session_start();
if (!isset($_SESSION['is_logged_in']) ||!$_SESSION['is_logged_in']) {header("Location: login.php");exit;
}
?>
<!DOCTYPE html>
<html>
<head><title>Home</title>
</head>
<body><h1>Welcome, <?php echo $_SESSION['username'];?></h1><!-- 页面内容 -->
</body>
</html>

3.2 安全的注销机制及记住登录状态功能

  1. 安全的注销机制:当用户点击注销按钮时,服务器需要销毁用户的 Session,清除相关的登录状态信息,以确保用户无法再以当前身份访问受保护的页面。在 PHP 中,使用session_destroy()函数来销毁整个 Session。同时,为了确保安全,还需要清除$_SESSION数组,并删除浏览器中的 Session ID Cookie(如果存在)。示例代码如下:
<?php
session_start();
// 清除所有Session变量
$_SESSION = array();
// 销毁Session
session_destroy();
// 删除Session ID Cookie
if (isset($_COOKIE[session_name()])) {setcookie(session_name(), '', time() - 3600, '/');
}
// 重定向到登录页面
header("Location: login.php");
?>
  1. 记住登录状态功能:结合 Cookie 和 Session 可以实现记住登录状态的功能。当用户在登录页面勾选 “记住我” 选项时,服务器在创建 Session 的同时,还会生成一个长期有效的 Cookie,将用户的唯一标识(如用户 ID 或加密后的用户名)和一个随机生成的令牌存储在 Cookie 中,并将该令牌与用户信息关联存储在服务器端(可以是数据库或文件系统) 。下次用户访问网站时,如果浏览器发送了这个 Cookie,服务器会验证 Cookie 中的令牌和用户标识是否匹配,如果匹配,则自动为用户创建 Session,实现自动登录。示例代码如下:
<?php
session_start();
// 获取表单数据
$username = $_POST['username'];
$password = $_POST['password'];
$remember = isset($_POST['remember'])? $_POST['remember'] : false;// 连接数据库验证用户(代码省略)if (mysqli_num_rows($result) == 1) {// 验证成功// 创建Session变量$_SESSION['is_logged_in'] = true;$_SESSION['username'] = $username;if ($remember) {// 生成随机令牌$token = bin2hex(random_bytes(32));// 存储令牌和用户信息到数据库(示例,实际需根据数据库结构调整)$conn = mysqli_connect("localhost", "username", "password", "database_name");$sql = "INSERT INTO remember_tokens (user_id, token, expires) VALUES ((SELECT id FROM users WHERE username = '$username'), '$token', NOW() + INTERVAL 30 DAY)";mysqli_query($conn, $sql);mysqli_close($conn);// 设置Cookiesetcookie('remember_token', $token, time() + 60 * 60 * 24 * 30, '/', '', true, true);}// 重定向到用户主页header("Location: home.php");
} else {// 验证失败$error = "Invalid username or password";
}
?>

在用户访问页面时,检查 “记住我” Cookie 的代码示例:

<?php
session_start();
if (!isset($_SESSION['is_logged_in']) ||!$_SESSION['is_logged_in']) {if (isset($_COOKIE['remember_token'])) {$token = $_COOKIE['remember_token'];$conn = mysqli_connect("localhost", "username", "password", "database_name");$sql = "SELECT user_id FROM remember_tokens WHERE token = '$token' AND expires > NOW()";$result = mysqli_query($conn, $sql);if (mysqli_num_rows($result) == 1) {$row = mysqli_fetch_assoc($result);$user_id = $row['user_id'];// 根据user_id获取用户名等信息(示例,实际需根据数据库结构调整)$sql = "SELECT username FROM users WHERE id = $user_id";$result = mysqli_query($conn, $sql);$row = mysqli_fetch_assoc($result);$username = $row['username'];// 创建Session变量$_SESSION['is_logged_in'] = true;$_SESSION['username'] = $username;// 重定向到用户主页header("Location: home.php");} else {// Cookie无效,删除Cookiesetcookie('remember_token', '', time() - 3600, '/');}mysqli_close($conn);}
}
?>

这样,通过上述安全的注销机制和记住登录状态功能的实现,可以提升用户体验和系统的安全性。

http://www.dtcms.com/a/308449.html

相关文章:

  • opencv解迷宫
  • Nuitka:将源码编译为 `.pyd`
  • vue+elementui实现问卷调查配置可单选、多选、解答
  • vector的增删改查模拟实现(简单版)【C++】
  • 【ProtoBuf】ProtoBuf安装
  • 力扣面试150(45/150)
  • 【C语言】深度剖析指针(三):回调机制、通用排序与数组指针逻辑
  • esp32s3 + ov2640,给摄像头加上拍照功能,存储到sd卡
  • 109㎡中古风家装:北京业之峰在朝阳区绘就温馨画卷
  • 【实际项目1.2-西门子PLC的报警监控思路】
  • Java多线程详解(1)
  • C#反射的概念与实战
  • [2025CVPR-小样本方向]ImagineFSL:基于VLM的少样本学习的想象基集上的自监督预训练很重要
  • 三方支付详解
  • SQL 中 WHERE 与 HAVING 的用法详解:分组聚合场景下的混用指南
  • 大数据平台数仓数湖hive之拉链表高效实现
  • 深度学习入门:用pytorch跑通GitHub的UNET-ZOO项目
  • 云服务器数据库
  • Camx-查看sensor mode 和效果参数
  • (LeetCode 每日一题) 2683. 相邻值的按位异或 (位运算)
  • 网络操作系统与应用服务器-1
  • SIwave 中 SIwizard 的 500 多个标准列表
  • 代码详细注释:演示多线程如何安全操作共享变量,使用互斥锁避免数据竞争。
  • Linux 文件系统基本管理
  • minidocx: 在C++11环境下运行的解决方案(二)
  • 网络攻击新态势企业级安全防御指南
  • Git分支管理:每个分支为什么这么命名?
  • Acrobat DC 应用安全配置:沙箱防护、数字签名
  • 了解微前端和SSO单点登录
  • Linux/Ubuntu 系统中打开火狐firefox、chromium浏览器失败