PHP Session 完整教程
目录
- 什么是 Session?
- Session vs. Cookie 的区别
- 如何使用 Session (基本步骤)
- 一个完整的登录与退出示例
- Session 的高级配置 (
php.ini) - Session 的安全最佳实践
- 常见问题与解决方案
什么是 Session?
Session(会话) 是一种在服务器端存储用户特定数据的机制,当用户访问一个网站时,服务器会为该用户创建一个唯一的 Session ID,并将其存储在客户端的 Cookie 中,在用户访问该网站的其他页面时,浏览器会自动携带这个 Session ID,服务器通过这个 ID 找到对应的 Session 数据,从而识别用户并保持其状态。

一个生动的比喻: 想象你去一家餐厅。
- Session ID:餐厅服务员递给你一个写有桌号的牌子(A05)。
- Session 数据:服务员会把你点的菜(牛排、沙拉)记录在 A05 号桌的订单上。
session_start():你坐下,服务员为你创建这个订单。$_SESSION:这张订单,上面记录了你的所有信息。session_destroy():你吃完饭,结账离开,服务员把 A05 号桌的订单销毁。
无论你在餐厅里走动(访问不同页面),服务员总能通过你的桌号(Session ID)找到你的订单(Session 数据),知道你点了什么。
Session vs. Cookie 的区别
| 特性 | Session | Cookie |
|---|---|---|
| 数据存储位置 | 服务器端 | 客户端 (用户的浏览器) |
| 安全性 | 高,敏感数据不暴露在客户端。 | 低,数据可以被用户查看、修改或删除。 |
| 存储大小 | 较大,受服务器内存或磁盘空间限制。 | 较小,通常限制在 4KB 左右。 |
| 生命周期 | 可配置,默认是浏览器关闭后失效,可以设置为长期有效。 | 可配置,可以设置为长期有效(如记住我功能)。 |
| 作用 | 存储用户登录状态、购物车、临时数据等敏感或大量信息。 | 存储少量非敏感数据,如用户偏好、Session ID 等。 |
核心区别:Session 数据存在服务器上,只通过一个不重要的 Session ID 来关联,因此更安全,Cookie 数据直接存在用户电脑上,因此安全性较低。
如何使用 Session (基本步骤)
使用 Session 非常简单,只需三个核心步骤。

第 1 步:启动 Session (session_start())
在任何操作 Session 数据之前,你必须先启动会话,这会检查客户端是否有 Session ID,如果没有,就创建一个新的;如果有,就加载服务器上对应的 Session 数据。
重要提示:
session_start()必须在任何 HTML 标签或echo输出之前调用,否则会报错。- 在整个应用中,你只需要调用一次
session_start(),通常放在一个公共的初始化文件(如config.php或session_start.php)中。
<?php
// 必须在最开始!
session_start();
// ... 其他代码 ...
?>
<html>
<head><title>我的网站</title></head>
<body>
...
</body>
</html>
第 2 步:存取 Session 数据 ($_SESSION)
一旦会话启动,你就可以通过 PHP 超全局变量 $_SESSION 来读写数据,它就像一个普通的 PHP 数组。
存入数据:

<?php session_start(); // 存储用户名 $_SESSION['username'] = '张三'; // 存储用户ID $_SESSION['user_id'] = 123; // 存储一个数组 $_SESSION['permissions'] = ['read', 'write', 'delete']; echo "Session 数据已设置。"; ?>
读取数据:
<?php
session_start();
// 检查某个 Session 变量是否存在
if (isset($_SESSION['username'])) {
echo "欢迎回来, " . $_SESSION['username'] . "!";
echo "<br>你的用户ID是: " . $_SESSION['user_id'];
} else {
echo "你还未登录。";
}
?>
更新数据: 和普通数组一样,直接重新赋值即可。
<?php session_start(); $_SESSION['username'] = '李四'; // 更新用户名 ?>
删除单个数据:
使用 unset() 函数。
<?php session_start(); // 删除 username 这个 Session 变量 unset($_SESSION['username']); // 再次访问 $_SESSION['username'] 将会返回 null ?>
第 3 步:销毁 Session (session_destroy())
当用户注销(登出)时,你需要彻底销毁整个会话,清除服务器上的所有 Session 数据。
注意:session_destroy() 会清空服务器端的 Session 文件,但不会清除客户端的 Session ID Cookie,为了完全“登出”,最好在调用 session_destroy() 后,手动将客户端的 Session ID Cookie 设置为过期。
<?php
// 1. 启动会话,以便能访问和销毁它
session_start();
// 2. 销毁所有 Session 数据
session_destroy();
// 3. (重要)清除客户端的 Session ID Cookie
// 如果不这样做,浏览器下次请求时仍会携带这个 ID,
// 虽然服务器找不到对应数据,但状态不干净。
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// 4. 重定向到登录页面或首页
header("Location: login.php");
exit();
?>
一个完整的登录与退出示例
这个例子将展示如何结合 Session 和表单实现一个简单的用户登录系统。
login.php (登录页面)
<?php
// 处理表单提交
if ($_SERVER["REQUEST_METHOD"] == "POST") {
// 假设的用户名和密码(实际应用中应从数据库验证)
$valid_username = 'admin';
$valid_password = 'password123';
$username = $_POST['username'];
$password = $_POST['password'];
if ($username === $valid_username && $password === $valid_password) {
// 登录成功,设置 Session
session_start();
$_SESSION['logged_in'] = true;
$_SESSION['username'] = $username;
// 重定向到受保护页面
header("Location: welcome.php");
exit();
} else {
$error = "用户名或密码错误!";
}
}
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">登录</title>
</head>
<body>
<h1>用户登录</h1>
<?php if (isset($error)) echo "<p style='color:red;'>$error</p>"; ?>
<form method="post" action="login.php">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" required>
<br><br>
<label for="password">密码:</label>
<input type="password" id="password" name="password" required>
<br><br>
<input type="submit" value="登录">
</form>
</body>
</html>
welcome.php (受保护的欢迎页面)
<?php
// 必须在每个需要 Session 的页面顶部调用
session_start();
// 检查用户是否已登录
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {
// 如果未登录,重定向到登录页
header("Location: login.php");
exit();
}
// 如果已登录,显示欢迎信息
?>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">欢迎页面</title>
</head>
<body>
<h1>欢迎, <?php echo htmlspecialchars($_SESSION['username']); ?>!</h1>
<p>这是一个只有登录用户才能看到的页面。</p>
<p>你的 Session 数据如下:</p>
<pre><?php print_r($_SESSION); ?></pre>
<br>
<a href="logout.php">退出登录</a>
</body>
</html>
logout.php (退出页面)
<?php
// 启动会话以销毁它
session_start();
// 销毁会话数据
session_destroy();
// 清除客户端的 session cookie
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// 重定向到登录页
header("Location: login.php");
exit();
?>
Session 的高级配置 (php.ini)
你可以在 php.ini 文件中配置 Session 的行为,一些重要的配置项:
session.save_path = "N;/path":指定 Session 文件存储的目录。N表示分级存储,可以提高大量文件时的性能。session.name = PHPSESSID:Session ID 在 Cookie 中存储的名称。session.cookie_lifetime = 0:Session ID Cookie 的有效期(秒)。0表示浏览器关闭后即失效。session.gc_maxlifetime = 1440:Session 数据在服务器端的最大存活时间(秒),超过这个时间,垃圾回收器会自动删除旧的 Session 文件。session.cookie_httponly = 1:防止客户端脚本访问 Session Cookie,有助于防止 XSS 攻击。强烈建议开启。session.use_strict_mode = 1:启用严格模式,可以防止 Session Fixation 攻击。强烈建议开启。
Session 的安全最佳实践
- 始终使用 HTTPS:在 HTTPS 环境中使用 Session,可以防止 Session ID 在传输过程中被窃取(中间人攻击)。
- 设置
session.cookie_httponly = 1:如上所述,防止 JavaScript 访问 Cookie。 - 设置
session.use_strict_mode = 1:防止攻击者通过已知 Session ID 进行会话固定攻击。 - 每次登录后重新生成 Session ID (
session_regenerate_id(true)):这是一个非常重要的安全措施,当用户成功登录时,调用session_regenerate_id(true)会销毁旧的 Session 文件并生成一个新的 ID,这可以彻底清除攻击者可能持有的旧 Session ID。// 在 login.php 验证成功后 session_start(); session_regenerate_id(true); // 重新生成 ID 并销毁旧的 $_SESSION['logged_in'] = true;
- 不要在 Session 中存储敏感信息:虽然 Session 数据在服务器端,但如果服务器被攻破,数据就会泄露,密码等绝对敏感的信息不应存入 Session,可以只存一个
user_id,然后通过user_id去数据库查询其他信息。 - 及时销毁不需要的 Session:用户退出时,务必调用
session_destroy()。
常见问题与解决方案
问题 1:Warning: session_start(): Cannot start session when headers already sent
- 原因:在
session_start()之前已经有任何输出(空格、换行、HTML 标签、echo等)。 - 解决:检查
session_start()之前的代码,确保没有任何输出,通常是由于文件开头有空格或 BOM 头造成的。
问题 2:登录后,刷新页面或进入其他页面,Session 数据丢失了。
- 原因:
- 没有在每个需要 Session 的页面都调用
session_start()。 session_start()代码有错误导致未能正确启动。- 服务器端的
session.save_path目录没有写入权限。
- 没有在每个需要 Session 的页面都调用
- 解决:
- 确保每个相关页面都在最顶部有
session_start();。 - 检查
php.ini配置和服务器目录权限。 - 使用
error_reporting(E_ALL);和ini_set('display_errors', 1);来查看具体的错误信息(开发环境)。
- 确保每个相关页面都在最顶部有
问题 3:如何让 Session 在浏览器关闭后仍然有效(“记住我”功能)?
- 解决:在登录成功后,手动设置一个长期的 Cookie。
// 在 login.php 登录成功后 if (isset($_POST['remember_me']) && $_POST['remember_me'] == 'on') { // 设置 Session ID Cookie 的有效期,30 天 $expiration = time() + (30 * 24 * 60 * 60); session_set_cookie_params($expiration); // 重新发送 Cookie session_start(); // 需要先启动才能设置参数 session_regenerate_id(true); // 重新生成 ID 以安全地延长有效期 }
PHP Session 是构建动态、交互式网站的基石,它简单易用,功能强大,是管理用户状态(如登录、购物车、用户偏好等)的首选工具。
核心流程回顾:
- 启动:在页面顶部调用
session_start()。 - 使用:通过
$_SESSION数组存取数据。 - 销毁:用户登出时,调用
session_destroy()并清除客户端 Cookie。
遵循安全最佳实践,你的 Session 机制将会非常可靠和安全。
