<返回目录     Powered by claud/xia兄

第10课: Cookie与Session

Cookie基础

Cookie是存储在客户端浏览器中的小型文本文件,用于在HTTP请求之间保持状态信息。

设置Cookie

<?php
// 基本语法
setcookie("name", "value", expire, path, domain, secure, httponly);

// 设置简单Cookie
setcookie("username", "张三");

// 设置有效期为7天的Cookie
$expire = time() + (86400 * 7);  // 7天
setcookie("username", "张三", $expire, "/");

// 设置30天有效期
setcookie("remember_me", "yes", time() + (86400 * 30), "/");

// 设置仅HTTPS传输的Cookie
setcookie("secure_data", "value", time() + 3600, "/", "", true, true);
?>

读取Cookie

<?php
// 读取Cookie
if (isset($_COOKIE["username"])) {
    echo "欢迎回来," . $_COOKIE["username"];
}

// 使用null合并运算符提供默认值
$username = $_COOKIE["username"] ?? "游客";

// 读取所有Cookie
print_r($_COOKIE);

// 检查Cookie是否存在
if (array_key_exists("user_id", $_COOKIE)) {
    $userId = $_COOKIE["user_id"];
}
?>

删除Cookie

<?php
// 设置过期时间为过去的时间
setcookie("username", "", time() - 3600, "/");

// 或者设置为1
setcookie("username", "", 1, "/");

// 删除多个Cookie
$cookies = ["username", "email", "token"];
foreach ($cookies as $cookie) {
    setcookie($cookie, "", time() - 3600, "/");
}
?>

Session基础

Session在服务器端存储用户数据,比Cookie更安全。每个用户有唯一的Session ID。

启动和使用Session

<?php
// 必须在任何输出之前启动Session
session_start();

// 设置Session变量
$_SESSION["user_id"] = 123;
$_SESSION["username"] = "张三";
$_SESSION["role"] = "admin";
$_SESSION["login_time"] = time();

// 读取Session
echo "用户ID: " . $_SESSION["user_id"];
echo "用户名: " . $_SESSION["username"];

// 检查Session是否存在
if (isset($_SESSION["user_id"])) {
    echo "用户已登录";
} else {
    echo "用户未登录";
}

// 使用数组存储复杂数据
$_SESSION["user"] = [
    "id" => 123,
    "name" => "张三",
    "email" => "zhang@example.com"
];
?>

Session配置

<?php
// 设置Session名称(在session_start()之前)
session_name("MY_APP_SESSION");

// 设置Session过期时间(秒)
ini_set('session.gc_maxlifetime', 1800);  // 30分钟

// 设置Session Cookie过期时间
ini_set('session.cookie_lifetime', 0);  // 0表示浏览器关闭时过期

// 设置Session保存路径
session_save_path("/tmp/sessions");

// 设置Session仅通过Cookie传递
ini_set('session.use_only_cookies', 1);

// 启用HttpOnly(防止JavaScript访问)
ini_set('session.cookie_httponly', 1);

// 启用Secure(仅HTTPS传输)
ini_set('session.cookie_secure', 1);

session_start();
?>

删除和销毁Session

<?php
session_start();

// 删除单个Session变量
unset($_SESSION["username"]);

// 清空所有Session变量
$_SESSION = [];

// 或使用session_unset()
session_unset();

// 完全销毁Session
session_destroy();

// 删除Session Cookie
if (isset($_COOKIE[session_name()])) {
    setcookie(session_name(), "", time() - 3600, "/");
}

// 完整的注销流程
session_start();
$_SESSION = [];
session_destroy();
setcookie(session_name(), "", time() - 3600, "/");
header("Location: login.php");
exit;
?>

用户登录系统

登录页面

<?php
// login.php
session_start();

// 如果已登录,重定向到首页
if (isset($_SESSION["logged_in"]) && $_SESSION["logged_in"] === true) {
    header("Location: dashboard.php");
    exit;
}

$error = "";

if ($_SERVER["REQUEST_METHOD"] === "POST") {
    $username = $_POST["username"] ?? "";
    $password = $_POST["password"] ?? "";
    $remember = isset($_POST["remember"]);

    // 验证用户(实际应该查询数据库)
    if ($username === "admin" && $password === "123456") {
        // 登录成功
        $_SESSION["logged_in"] = true;
        $_SESSION["user_id"] = 1;
        $_SESSION["username"] = $username;
        $_SESSION["login_time"] = time();

        // 记住我功能
        if ($remember) {
            setcookie("remember_token", bin2hex(random_bytes(32)),
                time() + (86400 * 30), "/");
        }

        // 重定向到仪表板
        header("Location: dashboard.php");
        exit;
    } else {
        $error = "用户名或密码错误";
    }
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>用户登录</title>
</head>
<body>
    <h1>用户登录</h1>

    <?php if ($error): ?>
        <p style="color: red;"><?php echo $error; ?></p>
    <?php endif; ?>

    <form method="post">
        <label>用户名:</label>
        <input type="text" name="username" required>

        <label>密码:</label>
        <input type="password" name="password" required>

        <label>
            <input type="checkbox" name="remember"> 记住我
        </label>

        <button type="submit">登录</button>
    </form>
</body>
</html>

受保护的页面

<?php
// dashboard.php
session_start();

// 检查登录状态
if (!isset($_SESSION["logged_in"]) || $_SESSION["logged_in"] !== true) {
    header("Location: login.php");
    exit;
}

// 检查Session超时(30分钟)
$timeout = 1800;
if (isset($_SESSION["last_activity"]) &&
    (time() - $_SESSION["last_activity"]) > $timeout) {
    session_unset();
    session_destroy();
    header("Location: login.php?timeout=1");
    exit;
}

// 更新最后活动时间
$_SESSION["last_activity"] = time();

$username = $_SESSION["username"];
?>

<!DOCTYPE html>
<html>
<head>
    <title>仪表板</title>
</head>
<body>
    <h1>欢迎,<?php echo htmlspecialchars($username); ?>!</h1>
    <p>登录时间:<?php echo date('Y-m-d H:i:s', $_SESSION["login_time"]); ?></p>
    <a href="logout.php">退出登录</a>
</body>
</html>

注销页面

<?php
// logout.php
session_start();

// 清空Session
$_SESSION = [];

// 删除Session Cookie
if (isset($_COOKIE[session_name()])) {
    setcookie(session_name(), "", time() - 3600, "/");
}

// 删除记住我Cookie
if (isset($_COOKIE["remember_token"])) {
    setcookie("remember_token", "", time() - 3600, "/");
}

// 销毁Session
session_destroy();

// 重定向到登录页
header("Location: login.php?logout=1");
exit;
?>

Session安全

Session劫持防护

<?php
session_start();

// 绑定Session到用户代理
if (!isset($_SESSION["user_agent"])) {
    $_SESSION["user_agent"] = $_SERVER["HTTP_USER_AGENT"];
} elseif ($_SESSION["user_agent"] !== $_SERVER["HTTP_USER_AGENT"]) {
    // Session可能被劫持
    session_unset();
    session_destroy();
    die("安全警告:Session验证失败");
}

// 绑定Session到IP地址(可选,可能影响移动用户)
if (!isset($_SESSION["ip_address"])) {
    $_SESSION["ip_address"] = $_SERVER["REMOTE_ADDR"];
} elseif ($_SESSION["ip_address"] !== $_SERVER["REMOTE_ADDR"]) {
    session_unset();
    session_destroy();
    die("安全警告:IP地址不匹配");
}
?>

Session固定攻击防护

<?php
// 登录成功后重新生成Session ID
session_start();

if ($loginSuccess) {
    // 重新生成Session ID
    session_regenerate_id(true);

    $_SESSION["logged_in"] = true;
    $_SESSION["user_id"] = $userId;
}

// 定期重新生成Session ID
if (!isset($_SESSION["created"])) {
    $_SESSION["created"] = time();
} elseif (time() - $_SESSION["created"] > 1800) {
    // 30分钟后重新生成
    session_regenerate_id(true);
    $_SESSION["created"] = time();
}
?>

购物车示例

<?php
session_start();

// 初始化购物车
if (!isset($_SESSION["cart"])) {
    $_SESSION["cart"] = [];
}

// 添加商品到购物车
function addToCart($productId, $quantity = 1) {
    if (isset($_SESSION["cart"][$productId])) {
        $_SESSION["cart"][$productId] += $quantity;
    } else {
        $_SESSION["cart"][$productId] = $quantity;
    }
}

// 从购物车移除商品
function removeFromCart($productId) {
    unset($_SESSION["cart"][$productId]);
}

// 更新商品数量
function updateCart($productId, $quantity) {
    if ($quantity <= 0) {
        removeFromCart($productId);
    } else {
        $_SESSION["cart"][$productId] = $quantity;
    }
}

// 获取购物车总数
function getCartCount() {
    return array_sum($_SESSION["cart"]);
}

// 清空购物车
function clearCart() {
    $_SESSION["cart"] = [];
}

// 使用示例
addToCart(101, 2);  // 添加商品ID 101,数量2
addToCart(102, 1);  // 添加商品ID 102,数量1
updateCart(101, 3); // 更新商品101数量为3
removeFromCart(102); // 移除商品102

echo "购物车商品总数: " . getCartCount();
?>

Cookie vs Session对比

Cookie特点: Session特点:
最佳实践:

实践练习

  1. 登录系统:实现完整的用户登录、注销功能
  2. 记住我:实现"记住我"功能,使用Cookie保持登录
  3. 购物车:使用Session实现购物车功能
  4. 访问统计:使用Cookie记录用户访问次数
  5. Session超时:实现Session自动超时功能
  6. 多语言切换:使用Cookie保存用户语言偏好
  7. 权限控制:基于Session实现不同角色的访问控制
  8. 防劫持:实现Session劫持检测机制