通用会话控制方案

一、会话控制概念

  • 目的:在无状态的 HTTP 请求间识别/鉴权用户身份并维持登录状态。
  • 核心问题:谁保存"用户状态"?(服务器 / 客户端 / 第三方认证服务器),以及如何安全地在多请求间传递该凭证(Cookie / Authorization header)。

二、传统方案:Cookie + 服务端 Session

1) 流程

  1. 用户登录,后端验证凭证(用户名/密码)。
  2. 后端在服务器端创建 session(比如 sessionId 对应的对象存在 Redis / DB / 内存),并返回 Set-Cookie: sessionId=xxx; HttpOnly; Secure; SameSite=Lax; Path=/ 响应头部信息。
  3. 浏览器自动带上 Cookie(同源或按 CORS 配置带上 credentials: 'include'),后端根据 sessionId 在 session store 查到用户信息并授权。

2) 示例(Express + express-session + Redis)

后端:

JavaScript 复制代码
const session = require('express-session');
const RedisStore = require('connect-redis')(session);
app.use(session({
  store: new RedisStore({ client: redisClient }),
  secret: process.env.SESSION_SECRET,
  name: 'sid',
  resave: false,
  saveUninitialized: false,
  cookie: {
    httpOnly: true,
    secure: true,      // 生产必须 https
    sameSite: 'lax',   // 或 'strict' / 'none'(配合跨域)
    maxAge: 24 * 3600 * 1000
  }
}));

前端(fetch):

JavaScript 复制代码
fetch('/api/profile', { credentials: 'include' })

3) 优点

  • 简单明确:后端完全控制会话(可以随时废弃/修改)。
  • 支持服务端会话失效(logout 立刻生效)。
  • 易于集成细粒度权限、会话统计与审计(存 Redis 的 session 可包含登录 IP、设备信息等)。

4) 缺点

  • 水平扩展需共享 session store(Redis)。
  • Session 存储和查询带来额外延迟与成本。
  • 跨域场景复杂:需要正确配置 Access-Control-Allow-CredentialsSet-CookieSameSite=None; Secure 等,避免安全问题。

三、JWT(JSON Web Token)方案概述

1) JWT 的基本思想(无状态 token)

  • 后端发放一个签名的 token(通常是 Access Token),包含用户 id、到期时间等。
  • 前端携带 token(通常放在 Authorization header 或者放入 HttpOnly cookie)向后端请求;后端不查 session store,而是直接验证 token 的签名与有效期,若通过则鉴权成功。

JWT 典型格式:header.payload.signature(Base64 编码)

JavaScript 复制代码
const jwt = require('jsonwebtoken');
const accessToken = jwt.sign({ uid: xxx }, process.env.JWT_SECRET, { expiresIn: '15m' });
const payload = jwt.verify(accessToken, process.env.JWT_SECRET);

2) 常见拓展

  • **短期 Access Token(如 5--15 分钟)**:放在内存或短寿命存储(不放 localStorage 更安全),用于 API 调用。
  • 长期 Refresh Token(如 14 天或更长)​:安全保存(​HttpOnly, Secure cookie),用于换取新的 Access Token。每次刷新都会发送新的 refresh token。服务端会保存 refresh token 的元数据(redis)。
  • Access Token 可放在 Authorization: Bearer <token>,或也可放在 HttpOnly cookie(同域 + credentials) 推荐将 Refresh Token 放 HttpOnly cookie,Access Token 放内存并通过 Authorization header 发送(减少 CSRF 风险)。

3) 优点

  • 无状态,后端不必保存 session(容易横向扩展,适合微服务 & 无状态后端),更适合移动端 SPA 等分布式鉴权。
  • Token 自包含(本身携带用户身份信息,后端只需验证 token 签名,就直接知道 token 是否有效以及用户信息,无需再查询数据库或者 session 存储),减少每次请求的 DB 查询。
  • 与 OAuth2 兼容,便于做 SSO 与第三方登录。

4) 缺点

  • 无法轻易撤销(access token 在有效期内一直可用,除非引入黑名单/撤销机制)。
  • 如果把 JWT 放在 localStorage(可被 JS 读取)会增加 XSS 风险;如果放 Cookie,则面临 CSRF 风险。

四、Cookie Session 与 JWT 的主要区别

表格 还在加载中,请等待加载完成后再尝试复制

五、安全策略

CSRF 防护(Cookie 自动带 credential 的情况下)

  • 优先:使用 SameSite=LaxSameSite=Strict ​
  • 对于必须 SameSite=None 的跨站场景,配合 **CSRF Token(双 submit cookie)**:
    • 后端在登录时设 Set-Cookie: CSRF-Token=xxx; HttpOnly=false; Secure(可被 JS 读取)
    • 前端每次请求在 header 中带 X-CSRF-Token: <value>,后端验证 header 与 cookie 值一致。
  • 或使用 Origin / Referer 检查(只允许来自可信域的请求)。

核心:CSRF 攻击者 ​可以发请求 ​,但 ​没法读 Cookie ​,无法把 token 放到 header 中,所以校验((req.cookies["CSRF-Token"] !== req.headers["X-CSRF-Token"]))。CSRF 攻击能发请求,但拿不到 cookie 内容 。

XSS 防护(避免 token 被窃取)

  • 对可执行 token 的存储避免使用 localStorage(HttpOnly cookie 防止 JS 读取)。

JWT 可撤销性策略

  • 短寿命 access token + refresh token (refresh token 存 HttpOnly cookie):
    • access token 过期快,可减少滥用窗口。
    • refresh token 在服务端有黑名单/DB 记录,必要时撤销(例如用户登出、密码变更)。
  • **token id(jti) + 存在服务端黑名单(Redis)**:在 logout / 强制下线时把 jti 写入黑名单并在验证时检查。黑名单可设置过期与分布式缓存。
相关推荐
武藤一雄7 分钟前
C#:进程/线程/多线程/AppDomain详解
后端·微软·c#·asp.net·.net·wpf·.netcore
我笔记17 分钟前
vue 子父调用
前端·javascript·vue.js
2401_8603195225 分钟前
在React Native鸿蒙跨平台开发中实现一个冒泡排序算法并将其应用于数据排序,如何进行复制数组以避免直接修改状态中的数组
javascript·算法·react native·react.js·harmonyos
华仔啊30 分钟前
RabbitMQ 如何保证消息不丢失和不重复消费?掌握这 4 个关键点就够了
java·后端·rabbitmq
学历真的很重要38 分钟前
PyTorch 机器学习工作流程基础 - 完整教程
人工智能·pytorch·后端·python·深度学习·机器学习·面试
毕设源码-朱学姐1 小时前
【开题答辩全过程】以 基于vue.js的校园二手平台为例,包含答辩的问题和答案
前端·javascript·vue.js
m0_471199631 小时前
【JavaScript】Set 和 Map 核心区别与实战用法(ES6 集合全解析)
前端·javascript·es6
执笔诉情殇〆1 小时前
使用AES加密方法,对Springboot+Vue项目进行前后端数据加密
vue.js·spring boot·后端
hoiii1871 小时前
MATLAB中主成分分析(PCA)与相关性分析的实现
前端·人工智能·matlab
小白|1 小时前
【OpenHarmony × Flutter】混合开发性能攻坚:如何将内存占用降低 40%?Flutter 引擎复用 + ArkTS 资源回收实战指南
开发语言·javascript·flutter