1.8 会话与 Cookie:往返车票与身份凭证


文档摘要

1.8 会话与 Cookie:往返车票与身份凭证 本节摘要:HTTP 本身不记人——每次请求对服务器来说都是新旅客。要让"登录过的旅客"下次来还被认出,就要发凭证:Cookie 存在旅客手里(浏览器),Session 存在站内台账(服务器)。本节讲两类凭证的机制与属性、登录态的最小可运行实现,并配时序图拆解一次受保护页面的完整握手。本节是 1.7 CSRF 令牌的机制基础,也是 2.6 安全专题的前置。 两张凭证的分工 Cookie 是旅客自己保管的纸条:服务器让浏览器代存几条键值,浏览器此后每次来站都自动出示。它适合放非敏感的偏好设置,比如"站内语言选了中文"。

本节摘要:HTTP 本身不记人——每次请求对服务器来说都是新旅客。要让"登录过的旅客"下次来还被认出,就要发凭证:Cookie 存在旅客手里(浏览器),Session 存在站内台账(服务器)。本节讲两类凭证的机制与属性、登录态的最小可运行实现,并配时序图拆解一次受保护页面的完整握手。本节是 1.7 CSRF 令牌的机制基础,也是 2.6 安全专题的前置。

两张凭证的分工

Cookie 是旅客自己保管的纸条:服务器让浏览器代存几条键值,浏览器此后每次来站都自动出示。它适合放非敏感的偏好设置,比如"站内语言选了中文"。Session 的机制叠在 Cookie 上:服务器为旅客建一份台账,台账编号(会话标识)放进一个小 Cookie,旅客只带编号,台账本身不离站。敏感数据放台账,不放纸条——分工就这么一条。

先看 Cookie 的读写与删除:

<?php // 设置:值、过期时间(time 加秒数)、可用路径、域 setcookie('lang', 'zh-CN', [ 'expires' => time() + 7 * 24 * 3600, // 7 天有效 'path' => '/', 'httponly' => true, // 禁止脚本读取,降低窃取面 'secure' => true, // 仅经加密通道传输 'samesite' => 'Lax', // 跨站携带限制,辅助防 CSRF ]); echo $_COOKIE['lang'] ?? '未设置'; // 读:本请求携带的 Cookie // 删除:把过期时间拨到过去 setcookie('lang', '', ['expires' => time() - 3600, 'path' => '/']);

三个安全属性要形成肌肉记忆:httponly 挡住浏览器脚本读取,secure 强制加密通道,samesite 限制跨站请求携带。新项目没有理由不带上它们——注意 setcookie 必须在任何正文输出之前调用,响应头一旦发出就晚了。

Session:站内台账怎么转

Session 的全套动作围绕 $_SESSION 这一个数组展开,机制却值得拆开看:session_start() 时 PHP 检查请求带来的会话标识,有则把对应台账从存储里装进 $_SESSION,没有则新建台账并下发新标识。验证码、购物车、登录态,都是台账上的条目。

<?php // step1 检票登记 session_start(); $_SESSION['boarded'] = ['G102', 'G208']; // 台账记一笔 // step2 同一旅客再次来访 session_start(); print_r($_SESSION['boarded']); // 台账调出来:G102、G208

图:会话凭证往返示意

图:会话凭证往返示意

再看一次受保护页面的完整握手,这次按时序走:

实战:登录态的最小实现

把机制落成三个文件的功能闭环:登录页验凭证后写台账,业务页查台账放行,登出页清台账。

<?php // login.php:检票发证 session_start(); $name = trim((string) ($_POST['name'] ?? '')); $pass = (string) ($_POST['pass'] ?? ''); // 演示用固定口令;真实系统查数据库并比对散列(2.2 与 2.6 节展开) if ($name === 'station' && $pass === 'secret') { session_regenerate_id(true); // 换新小票,防会话固定攻击 $_SESSION['uid'] = 1; $_SESSION['uname'] = $name; header('Location: dashboard.php'); exit; } exit('凭证不符');
<?php // dashboard.php:验票放行 session_start(); if (empty($_SESSION['uid'])) { header('Location: login.html'); // 无凭证者请先检票 exit; } echo '欢迎回来,' . htmlspecialchars($_SESSION['uname'], ENT_QUOTES, 'UTF-8');
<?php // logout.php:收回凭证 session_start(); $_SESSION = []; // 清空台账 session_destroy(); // 销毁台账本 echo '已登出,期待再会';

三个文件连起来读:登录成功后 session_regenerate_id(true) 换新编号,堵住"攻击者预先固定编号"的路子;业务页只认台账里的 uid;登出先清数组再销毁台账。麻雀虽小,登录态该有的关节都有了,第 2.6 节会在此基础上加密码散列与限流。

会话还有两件日常运维小事值得交代。其一,会话有效期不是无限:PHP 默认按"若干分钟无动作即回收台账"运作(由配置项控制),旅客隔夜回来被要求重新登录多半是它——产品上要延长,改配置加主动续期;安全上想收紧,缩短空闲回收期。其二,多台服务器部署时,台账默认存在各自本机的文件里,旅客这次被分到甲机、下次被分到乙机,票就"查无此账"了——解法是把台账存到共享存储或 Redis(2.5 节的外置缓存再次登场),这是从单机走向部署冗余时必然遇到的一站,先在这里留个心眼。

常见坑

⚠️ 输出之后才 session_startsetcookie:响应头已发出,函数报警失效。所有头部动作放在脚本最前面。

⚠️ 敏感数据进 Cookie:把用户角色、权限明文塞进 Cookie 等于让旅客自己涂改车票,敏感项只进 Session。

本节要点回顾

  • HTTP 不记人:跨请求识别靠凭证,Cookie 在旅客侧、Session 在站内侧,编号可外带、内容不外带。
  • 三件套属性httponlysecuresamesite 是新项目 Cookie 的默认配置。
  • 登录态三件套:登录写台账并换编号、业务页验标记、登出清空并销毁。
  • 时序图动作session_start 是每次握手的起点,台账调取成功与否决定放行分支。

下一节处理"出了岔子怎么办":错误处理与调试,月台的广播系统与事故登记簿。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U