6.3 Session 与 Cookie


文档摘要

6.3 Session 与 Cookie HTTP 本身没有记忆:上一个请求登的录,下一个请求就不认账。会话机制在无状态的协议上补出一层「记名册」——服务端开档案(Session),浏览器带凭据(Cookie),凭据对上档案,同一用户跨请求的身份就立住了。本节是安检闸口的收尾,承接 6.2 的「中间状态」思维但换了立场:缓存可以丢,会话不能错——把 A 的请求当成 B,是比慢更严重的事故。学完你应当能配置会话驱动、安全地操作 Cookie,并处理前后端分离后的跨域凭据问题。 会话的工作方式与驱动 流程一句话:首次请求里框架生成会话编号,随响应 Set-Cookie 下发;浏览器后续请求自动带回编号,框架凭编号找到服务端档案。档案存哪由驱动决定:File 驱动把档案落成小文件,单机够用;

HTTP 本身没有记忆:上一个请求登的录,下一个请求就不认账。会话机制在无状态的协议上补出一层「记名册」——服务端开档案(Session),浏览器带凭据(Cookie),凭据对上档案,同一用户跨请求的身份就立住了。本节是安检闸口的收尾,承接 6.2 的「中间状态」思维但换了立场:缓存可以丢,会话不能错——把 A 的请求当成 B,是比慢更严重的事故。学完你应当能配置会话驱动、安全地操作 Cookie,并处理前后端分离后的跨域凭据问题。

会话的工作方式与驱动

流程一句话:首次请求里框架生成会话编号,随响应 Set-Cookie 下发;浏览器后续请求自动带回编号,框架凭编号找到服务端档案。档案存哪由驱动决定:File 驱动把档案落成小文件,单机够用;Redis 驱动把档案放进共享存储,多机部署与高并发下的标准答案——判据与 6.2 的缓存选型完全一致,跟着部署形态走。

use think\facade\Session; // 写与读:登录态与购物车 Session::set('user_id', $user->id); Session::set('cart', ['book_1024' => 2]); $userId = Session::get('user_id'); Session::delete('cart'); // 闪存:只活到下个请求的一次性数据,表单回填与提示语专用 Session::flash('tip', '收货地址已更新'); // 登出与改密后:销毁旧档案,凭据一并作废 Session::destroy();

flash 是最容易被忽略的好东西:操作成功的提示语、验证失败要回填的旧输入,都只在下个请求有用,闪存让它们自生自灭,不用手工清理。destroy 的时机要记牢:登录、登出、改密码三个动作都应更换或销毁会话——改密码后若不销毁旧会话,被偷走的凭据就还能继续用,这正是会话固定攻击的标准剧本。换句话说,凭据被偷后仍然有效的窗口,是安全审计里的重点检查项,销毁动作就是在压缩这个窗口。

Cookie 不只是「服务端放浏览器手里的小纸条」,它的每个属性都是一道闸:

use think\facade\Cookie; // 框架配置 config/cookie.php 里的关键项 return [ 'expire' => 0, // 时效:0 为浏览器会话级,关窗即清 'path' => '/', // 作用路径:限定凭据只在哪些路径下发 'domain' => '', // 作用域:默认当前域,主域共享要显式配置 'secure' => true, // 安全位:仅 HTTPS 传输 'httponly' => true, // 禁止脚本读取:挡住 XSS 偷凭据 'samesite' => 'Lax', // 跨站限制:配合 6.1 的令牌拦 CSRF ];

四件套各管一件事:时效决定凭据活多久——「记住登录」的本质是延长它,支付类操作反而用会话级;域与路径决定凭据发给谁——子站共享登录态用主域 Cookie,其余场景从严;安全位保证凭据不裸奔在明文链路上;HttpOnly 保证页面脚本偷不走——XSS 漏洞(7.2)哪怕发生,偷凭据这条路也是堵死的。业务侧写 Cookie 只放非敏感的偏好项(主题、语言),身份凭据交给会话编号这一张票,别把用户名密码塞进 Cookie——那是把档案复印一份交给访客。

跨域与前后端分离的凭据问题

接口服务与页面不同域(或走 App、小程序)时,会话凭据的传递多两步配置。前端请求要带凭据声明,后端要明确放行:

// 中间件侧:CORS 放行要写具体来源,凭据模式下通配符无效 header('Access-Control-Allow-Origin: https://shop.example.com'); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Allow-Headers: Content-Type, X-Requested-With');

三条纪律:其一,Allow-Credentials 打开时来源必须精确列出,通配符星号与凭据模式互斥,写了星号浏览器直接拒收;其二,跨域 Cookie 的域属性要升到共同主域,否则子域之间互不认票;其三,前后端彻底分离且多端并存的项目,认真评估「令牌方案替代会话」——会话凭据靠浏览器自动携带,非浏览器端要手工管理,与其硬凑不如换凭据机制,这笔选型账在架构期就要算。

动手练习:把登录态搬到 Redis 并验证四件套

背景:练习项目的会话还在 File 驱动上,本地登录正常但准备多机部署。操作:会话驱动切到 Redis(复用 6.2 的连接),登录后到 Redis 里找到会话键确认档案内容;把 Cookie 配置的 securehttponlysamesite 逐项打开,用浏览器开发者工具观察响应头与 Cookie 面板的变化;再用一段控制台脚本尝试读取 Cookie,验证 HttpOnly 生效。结果示例:脚本读到空值,SameSite=Lax 的跨站 POST 请求不再携带凭据。解读:每开一个属性都可能「弄坏」某个旧流程——老站点从 HTTP 迁 HTTPS 时 secure 要排在整个链路之后。变式:实现「改密码后强制全员下线」——给会话档案加一个版本号字段,密码变更时版本号自增,旧会话校验失败即销毁,思考为什么遍历删除所有会话在集群里不可靠。

💡 关键直觉:会话是「用服务端存储换协议记忆」的交易,Cookie 属性是这张交易的合同条款——时效、域、路径、安全位每一条都对应一种风险敞口,签合同之前先读懂每一款。

会话排错小抄

会话问题有三种高频长相。刷新即掉线:先查 Cookie 的域与路径配置——写在了子域或深路径,其他请求带不上凭据;再查 secure 开关与当前协议是否匹配,HTTP 站点配了 secure,凭据直接不下发。多机环境半数请求掉线:典型的会话存储没共享——两台机器各自存档,凭据到了另一台就查无此人,把驱动切到 Redis 即愈。「我明明登录了」类灵异:优先查会话与缓存是否共用了存储且被某次清理连坐(6.2 的坑重现),把两套存储分开后自愈。三张小抄的共同点:会话问题几乎不出在代码逻辑,出在配置与部署差异——按「凭据带没带上、档案找不找得到」两问对号入座即可。

本节要点回顾

  • 无状态协议的记忆层:服务端档案加浏览器凭据,凭据对上档案才有身份。
  • 驱动跟着部署走:单机 File、多机 Redis,与缓存选型同一判据。
  • 三个动作换凭据:登录、登出、改密码都应销毁或更换会话,压缩凭据被偷后的有效窗口。
  • 属性四件套:时效管寿命,域与路径管发放范围,安全位与 HttpOnly 管传输与窃取。
  • 跨域凭据三纪律:精确来源、主域提升、必要时改用令牌方案。

安检闸口三道通道到此全部走完。带着核验过的数据继续前行,下一章换一副眼镜:假设每一环都可能被恶意利用,防线该怎么层层布设——第 7 章安全防线见。


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