阶段五:HttpOnly Cookie 登录持久化
从零构建带AI流式对话的Vue2全栈应用-CSDN博客本文是对这篇文章阶段五的讲解一、阶段五为什么要改 Token 保存方式阶段四Token 保存在 Vuex 前端 JavaScript 可以读取 Token 刷新后 Token 消失阶段五Token 保存在 HttpOnly Cookie JavaScript 不能读取 Token 浏览器自动携带 Cookie 刷新后可以恢复登录二、Cookie 是什么Cookie 是浏览器保存的一小段数据。服务器返回Set-Cookie: session_tokenabc123浏览器保存后之后访问同一个网站会自动发送Cookie: session_tokenabc123前端页面不需要自己把 Token 加到请求头。三、cookie-parser安装npm install cookie-parser代码const cookieParser require(cookie-parser) app.use(cookieParser())它会把请求 Cookie 解析到req.cookies例如req.cookies.session_token可以获取会话 Token。四、Cookie 配置const sessionCookieOptions { httpOnly: true, secure: false, sameSite: lax, path: /, maxAge: 24 * 60 * 60 * 1000 }1.httpOnlyhttpOnly: true表示前端 JavaScript 不能读取这个 Cookie。下面代码读不到会话 Tokendocument.cookie这样可以降低恶意脚本直接窃取 Token 的风险。2.securesecure: false表示 HTTP 也允许发送 Cookie。本地项目使用http://localhost所以必须暂时是false。正式上线使用 HTTPS 时应该改为secure: true3.sameSitesameSite: lax用于限制跨网站请求携带 Cookie。它可以减少一部分 CSRF 风险。4.pathpath: /表示这个 Cookie 对整个网站路径都有效。包括/api/users /api/auth/me /api/ai/stream5.maxAgemaxAge: 24 * 60 * 60 * 1000计算过程24 小时 × 60 分钟 × 60 秒 × 1000 毫秒所以保存 24 小时。五、登录成功设置 Cookieres.cookie( SESSION_COOKIE_NAME, token, sessionCookieOptions )可以理解成让响应头包含Set-Cookie: session_tokentoken内容然后后端只返回用户res.json({ code: 0, data: { user: codeRecord.user } })不再返回token因为前端不应该读取 HttpOnly Token。六、阶段五鉴权中间件const token req.cookies[SESSION_COOKIE_NAME]不再读取req.headers.authorization而是读取 Cookie。完整流程浏览器请求 /api/users ↓ 自动携带 Cookie ↓ cookie-parser 解析 ↓ req.cookies.session_token ↓ loginSessions.get(token) ↓ 找到当前用户 ↓ next()七、为什么还需要后端loginSessionsCookie 中只保存一个随机 Tokenabc123真正用户信息保存在后端loginSessions.set(token, { user: mockWechatUser, expiresAt: ... })对应关系abc123 ↓ 微信学习者不能只相信浏览器自己传来的用户名称。应该由后端根据 Token 查找真实用户。八、/api/auth/me的作用刷新页面后Vuex 中currentUser null但浏览器可能仍有有效 Cookie。前端调用GET /api/auth/me浏览器自动带 Cookie。后端返回req.currentUser前端重新把用户放进 Vuex。所以刷新页面 ↓ Vuex 清空 ↓ 调用 /api/auth/me ↓ Cookie 仍有效 ↓ 后端返回用户 ↓ Vuex 恢复 currentUser九、authChecked为什么必要Vuexstate: { currentUser: null, authChecked: false }页面刚启动时currentUser null此时不能立即判断用户没登录因为还没有检查 Cookie。所以增加authChecked含义false还没有询问后端 true已经完成登录状态检查十、Vuex ActioninitializeAuthasync initializeAuth({ state, commit }) { if (state.authChecked) { return Boolean( state.currentUser ) } try { const user await getCurrentUser() commit( setCurrentUser, user ) return true } catch (error) { commit(clearAuth) return false } finally { commit( setAuthChecked, true ) } }参数解构原本 Vuex action 参数是context可以写async initializeAuth(context) { context.state context.commit(...) }这里使用解构async initializeAuth({ state, commit })直接取出state和commit。为什么finally设置authChecked无论Cookie 有效 Cookie 无效 后端错误都说明检查已经完成。所以放在finallycommit(setAuthChecked, true)十一、路由守卫为什么变成 asyncrouter.beforeEach( async (to, from, next) { if (!store.state.authChecked) { await store.dispatch( initializeAuth ) } // 再判断是否登录 } )必须先等待/api/auth/me返回。错误流程currentUser 初始 null 立即判断未登录 跳到登录页 之后 /auth/me 才返回正确流程先等待 /auth/me ↓ 恢复 currentUser ↓ 再判断能否进入后台十二、Axios 的withCredentialsconst service axios.create({ withCredentials: true })它表示请求允许携带 Cookie 等凭证。当前开发代理是同源形式浏览器本来就会携带 Cookie。保留这个配置可以让后续前后端分开部署时更容易调整。十三、退出登录后端loginSessions.delete(token)删除服务器中的会话。然后res.clearCookie( SESSION_COOKIE_NAME, cookieOptions )通知浏览器删除 Cookie。前端commit(clearAuth)清空当前用户。完整退出流程点击退出 ↓ POST /api/auth/logout ↓ 后端删除 session ↓ 后端清除 Cookie ↓ Vuex 清除用户 ↓ 跳转 /login十四、阶段五的限制目前会话保存在const loginSessions new Map()后端一旦重启Map 被清空 浏览器 Cookie 还在 后端找不到对应 session 返回登录失效正式项目通常使用Redis 数据库 Session 服务保存会话。

相关新闻

番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理

番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理

番茄钟终极指南:如何用Tomodoro实现深度专注与高效时间管理 【免费下载链接】tomodoro A pomodoro web app with PIP mode, white noise generation, tasks and more! 项目地址: https://gitcode.com/gh_mirrors/to/tomodoro 你是否曾坐在电脑前数小时&#…

2026/10/10 10:35:27 阅读更多 →
HarmonyOS:ArkTS数据模型的设计与演进实战

HarmonyOS:ArkTS数据模型的设计与演进实战

引子:数据设计好了,UI 就是套模板 星空运势应用经历了两次数据结构的变化。第一版是四个文件——Types.ts、SignsData.ts、TarotData.ts、Constants.ts,每个文件职责单一。重构后合并成了一个 DataModel.ets,12 星座的数据从 5 个…

2026/10/11 16:41:13 阅读更多 →
TMS320F2838x DMA通道优先级配置与高优先级模式实战解析

TMS320F2838x DMA通道优先级配置与高优先级模式实战解析

1. 项目概述:为什么DMA优先级配置是嵌入式开发者的必修课在嵌入式系统开发,尤其是基于TMS320F2838x这类高性能实时微控制器的项目中,直接内存访问(DMA)模块的性能直接决定了整个系统的实时性和效率。很多工程师在初次接…

2026/10/8 8:38:47 阅读更多 →

最新新闻

OpenCode 终端 AI 编程代理:从安装配置到实战避坑指南

OpenCode 终端 AI 编程代理:从安装配置到实战避坑指南

1. 从一个终端窗口说起:OpenCode 到底在解决什么问题第一次听说 OpenCode 的人,多半是在某个技术群里看到别人贴了一张终端截图——黑底绿字,光标闪烁,敲几行命令就能让 AI 帮忙改代码、跑测试、查文档。很多人第一反应是"这…

2026/10/15 2:00:12 阅读更多 →
虚拟线程与常见第三方开源库的兼容性避坑清单:数据库连接池、HttpClient 与序列化

虚拟线程与常见第三方开源库的兼容性避坑清单:数据库连接池、HttpClient 与序列化

在 Spring Boot 3 工程中,开启虚拟线程(Virtual Threads)只需要轻飘飘的一行配置: spring.threads.virtual.enabledtrue很多技术负责人看到官网宣传的“平替传统线程、百万并发无压力”,便以为只要把这一行配置打上&am…

2026/10/15 2:00:12 阅读更多 →
专科生必备:9款降AI率工具实测与选型指南

专科生必备:9款降AI率工具实测与选型指南

1. 项目背景与核心价值2026年的职场环境对专科生的技术素养提出了更高要求。随着AI工具在工作场景中的渗透率突破60%,掌握降AI率工具已成为专科生提升就业竞争力的关键技能。这类工具能有效降低工作流程中的AI依赖度,帮助从业者保持独立思考能力和核心业…

2026/10/15 2:00:12 阅读更多 →
搜索热词“superpowers”拆解:安装前必须搞清的增强工具与模组逻辑

搜索热词“superpowers”拆解:安装前必须搞清的增强工具与模组逻辑

1. 当“superpowers”成为一个搜索热词,它到底在指什么“superpowers”这个词最近在搜索框里出现的频率明显高了起来,连带“想要安装superpowers”这样的长尾词也冒了出来。第一次看到这个组合的人大概率会愣一下:这到底是一个软件、一个插件…

2026/10/15 2:00:12 阅读更多 →
Web安全入门:读懂Web世界里的攻防

Web安全入门:读懂Web世界里的攻防

Web安全入门:读懂Web世界里的攻防一、什么是Web安全二、Web安全为什么很重要三、Web常见漏洞简介(OWASP Top10核心)四、Web攻击的基本思路五、Web安全防护思路六、Web安全学习方向结尾一、什么是Web安全 Web安全,全称Web应用安全…

2026/10/15 2:00:12 阅读更多 →
Gitea局域网服务器Local: No connection could be made because the target machine actively refused it.

Gitea局域网服务器Local: No connection could be made because the target machine actively refused it.

现象:使用Gitea 当git仓库管理A电脑当服务器,B电脑推送,有lfs大文件A电脑可以自己推送。B电脑推送失败:提示git.exe push --progress -- "192" master:master warning: use of unencrypted HTTP remote URLs is not re…

2026/10/15 1:59:12 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →