Cookie 和 Session 是什么
HTTP 是无状态协议,服务器无法记住上一次请求是谁发的。为了维持“会话”状态,就有了两种常用方案:
Cookie:数据存在客户端浏览器,每次请求自动带上Session:数据存在服务器端,客户端只保存一个 session id
Cookie 的基本用法
设置 Cookie
<?php
// setcookie(名字, 值, 过期时间, 路径, 域名)
setcookie('username', 'zhangsan', time() + 3600, '/');
?>
time() + 3600 表示 1 小时后过期;不传过期时间或传 0,则浏览器关闭后失效(会话级 Cookie)。
读取 Cookie
<?php
if (isset($_COOKIE['username'])) {
echo '欢迎你:' . $_COOKIE['username'];
} else {
echo 'Cookie 不存在';
}
?>
注意:setcookie() 之后,本次请求的 $_COOKIE 里还没有值,要刷新后的下一次请求才能读到。
删除 Cookie
<?php
// 把过期时间设为过去即可
setcookie('username', '', time() - 3600, '/');
?>
Session 的基本用法
使用 Session 前必须先调用 session_start(),且它前面不能有任何输出。
写入 Session
<?php
session_start();
$_SESSION['username'] = 'zhangsan';
$_SESSION['login_time'] = time();
?>
读取 Session
<?php
session_start();
if (isset($_SESSION['username'])) {
echo '当前用户:' . $_SESSION['username'];
} else {
echo '未登录';
}
?>
删除 Session
<?php
session_start();
// 删除某个值
unset($_SESSION['username']);
// 清空所有 Session 数据
$_SESSION = [];
// 销毁整个会话(包括 session id)
session_destroy();
?>
Session 的过期时间
可以在 php.ini 里配置:
session.gc_maxlifetime = 1440
session.cookie_lifetime = 0
也可以在代码里临时设置:
<?php
ini_set('session.gc_maxlifetime', 3600);
session_start();
?>
一个简单的登录示例
login.php:
<?php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$user = $_POST['username'] ?? '';
$pass = $_POST['password'] ?? '';
if ($user === 'admin' && $pass === '123456') {
session_start();
$_SESSION['username'] = $user;
header('Location: index.php');
exit;
}
echo '账号或密码错误';
}
?>
<form method="post">
用户名:<input name="username"><br>
密码:<input type="password" name="password"><br>
<button type="submit">登录</button>
</form>
index.php:
<?php
session_start();
if (empty($_SESSION['username'])) {
header('Location: login.php');
exit;
}
echo '已登录:' . htmlspecialchars($_SESSION['username']);
?>
两者的对比与选择
| 对比项 | Cookie | Session |
|---|---|---|
| 存储位置 | 客户端 | 服务器 |
| 安全性 | 较低,用户可查看修改 | 较高 |
| 大小限制 | 一般 4KB 左右 | 受服务器限制 |
| 生命周期 | 可设过期时间 | 默认会话结束失效 |
| 典型场景 | 记住用户名、偏好设置 | 登录状态、购物车 |
经验做法:敏感数据(如登录状态、权限信息)放 Session,不敏感的偏好配置才放 Cookie。输出到页面的内容记得用 htmlspecialchars() 转义,防止 XSS。