常用网站登录鉴权方案

Cookie-Session 方案 vs JWT Token 方案 超详细对比讲解

一、Cookie + Session 登录鉴权(服务端有状态方案)

1. 完整工作流程

步骤1:登录验证

用户提交账号密码,后端校验账号正确:

  1. 服务端生成唯一随机字符串 SessionID
  2. 在服务端存储映射关系:SessionID → 用户信息、过期时间、设备、权限
    • 单体:内存存储
    • 分布式集群:Redis / MySQL 共享会话
  3. 通过 HTTP 响应头 Set-Cookie 将 SessionID 下发给浏览器
Set-Cookie: SID=xxxxsessionidxxx; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=86400

步骤2:后续请求自动携带Cookie

浏览器规则:同域名下所有请求自动带上当前域名所有Cookie,无需前端手动处理。
请求自动带上:Cookie: SID=xxxxsessionidxxx

步骤3:后端鉴权

  1. 从请求 Cookie 取出 SID
  2. 查询 Redis/内存,判断 Session 是否存在、是否过期
  3. 存在则取出用户信息执行业务;不存在返回401未登录

步骤4:登出/过期

  • 主动登出:后端删除Redis中对应Session记录,下次请求失效
  • 被动过期:Redis设置TTL,超时自动清除会话

2. Cookie 关键安全属性(必配置)

属性 作用
HttpOnly JS无法通过document.cookie读取,防御XSS窃取会话
Secure 仅HTTPS协议下才发送Cookie,HTTP明文不传输
SameSite=Lax/Strict 跨站请求不会自动携带Cookie,防御CSRF攻击
Path=/ Cookie作用域整个网站,限制路径可缩小泄露范围
Max-Age 设置会话有效期

3. 优点

  1. 前端零成本:浏览器自动管理,不用手动存储、手动拼接请求头
  2. 数据存在服务端,前端只存ID,敏感信息不会暴露前端
  3. 可控性极强:后端随时删除Session实现强制下线、踢人
  4. 简单易上手,传统框架原生支持(Spring Session、PHP Session)
  5. CSRF配合防护后安全性很高

4. 缺点

  1. 服务端有状态
    集群多台服务器部署时,必须做Session共享(Redis),否则负载均衡分发到不同机器会登录失效;扩容成本更高。
  2. 跨域限制严重
    Cookie遵循同源策略,前端分离项目(前端域名a.com,后端api.b.com)默认无法携带Cookie,需要后端配置CORS + withCredentials,小程序、APP跨端兼容麻烦。
  3. CSRF 攻击风险
    第三方钓鱼网站可构造跨站请求,浏览器自动带上本站Cookie,必须额外开发CSRF Token。
    备注:
  4. 移动端适配差
    APP、小程序、第三方客户端不支持浏览器Cookie机制,无法直接使用。

5. 适用场景

传统单体后台管理系统、纯服务端渲染网站(JSP/Thymeleaf/PHP模板)、内部OA系统。

6. 配套安全方案:CSRF Token

因为Cookie自动携带,跨站伪造请求会带上有效会话,解决方案:

  1. 页面加载时后端生成随机CSRF Token存入Session
  2. 前端将Token存在localStorage或表单隐藏域
  3. 所有修改数据接口(POST/PUT/DELETE)请求头携带 X-CSRF-Token
  4. 后端同时校验SessionID和CSRF Token是否匹配

二、JWT(JSON Web Token)无状态令牌方案

1. JWT 结构说明

三段用 . 分隔的 Base64URL 字符串,整体无加密,仅签名防篡改
Header.Payload.Signature

  1. Header 头部(算法)
    Base64编码JSON,指定签名算法,常用 HS256(对称密钥)、RS256(非对称公私钥)
    {"alg":"HS256","typ":"JWT"}
    
  2. Payload 载荷(业务数据)
    存放声明信息,分为标准声明和自定义业务字段

    ⚠️ 仅Base64编码,可直接解码查看,禁止存放密码、银行卡等敏感数据
    标准字段:
    - iss:签发者
    - exp:过期时间戳(必填)
    - sub:用户唯一标识
    - iat:签发时间
    自定义:userId、role、username等

  3. Signature 签名(防篡改核心)
    公式:HMACSHA256(base64(Header) + "." + base64(Payload), 密钥)
    后端校验时使用同一密钥重新计算签名,和传入Token签名对比,不一致说明数据被篡改,直接拒绝。

2. JWT 完整登录流程(标准双Token方案:Access + Refresh)

单Token存在无法主动注销的缺陷,生产环境一律使用双令牌模式

1)登录阶段

账号密码校验通过,后端生成两个令牌:

  1. AccessToken(短期,5~30分钟):接口鉴权使用,带用户信息
  2. RefreshToken(长期,7~30天):存入Redis/数据库,仅用于刷新AccessToken,不参与业务鉴权

返回给前端,前端存储:

  • AccessToken:localStorage / sessionStorage
  • RefreshToken:推荐HttpOnly Cookie存储(提升安全)

2)业务请求鉴权

前端每次接口手动在请求头携带:

Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

后端处理:

  1. 截取Bearer后的JWT字符串
  2. 使用密钥校验签名是否合法(判断是否被篡改)
  3. 校验exp过期时间
  4. 校验通过直接解析Payload获取用户ID、权限,无需查询存储

3)Token过期无感刷新

前端拦截接口401过期响应,自动调用刷新接口:

  1. 提交RefreshToken
  2. 后端查询Redis判断RefreshToken是否有效、未被注销
  3. 有效则生成新AccessToken返回前端,旧AccessToken继续用到过期
  4. RefreshToken失效则跳转登录页

4)登出/强制下线

单纯JWT无状态无法失效已签发未过期Token,依靠RefreshToken管控:

  1. 用户登出:后端删除Redis中该用户的RefreshToken
  2. 后台强制踢人:清除对应RefreshToken,用户无法刷新新Token,AccessToken短期过期后自动下线
  3. 高危场景补充:Redis黑名单存储未过期但作废的AccessToken,短期拦截

3. JWT 优点

  1. 完全无状态,分布式友好
    鉴权只校验签名,不需要服务端存储会话,多机器集群、微服务无需共享存储,扩容简单。
  2. 天然支持跨域、多端
    Token放在请求Header,不受Cookie同源限制;网页、APP、小程序、第三方客户端通用。
  3. 自带用户信息,减少DB查询
    Payload内置用户ID、角色权限,高频接口不用每次查库获取用户身份。
  4. 适配微服务、单点登录SSO
    统一身份中心签发JWT,所有微服务共用一套密钥校验,不用会话共享。

4. JWT 缺点

  1. 无法立即失效(原生缺陷)
    只要AccessToken未过期、签名合法就有效,单纯单JWT方案做不到强制下线,必须搭配RefreshToken+Redis黑名单弥补。
  2. Payload明文可解码,不能存敏感数据
    Base64只是编码不是加密,任何人拿到Token都能读出里面所有信息。
  3. Token体积大,增加网络开销
    相比短SessionID,JWT字符串很长,每次请求携带会增加带宽消耗。
  4. 刷新逻辑复杂,前端需要封装无感刷新拦截器
    要处理401重试、并发刷新锁、过期跳转等逻辑,开发成本高于Cookie-Session。
  5. XSS窃取风险更高
    多数项目AccessToken存在localStorage,JS可读取,XSS漏洞会直接盗取Token;Cookie的HttpOnly可规避该问题。

5. 适用场景

前后端分离SPA网站、小程序、APP、微服务、第三方开放登录、跨域项目。

6. JWT安全优化手段

  1. 使用短期AccessToken,降低被盗后的有效期风险
  2. RefreshToken存入HttpOnly Cookie,避免前端JS读取
  3. 非对称加密RS256,私钥签发、公钥校验,密钥泄露风险更低
  4. 绑定设备指纹,同一RefreshToken仅限登录设备使用
  5. 增加黑名单机制,支持主动注销

三、Cookie-Session vs JWT 核心横向对比

对比维度 Cookie + Session JWT(Access+Refresh)
状态 有状态,服务端存储Session映射 半无状态,仅RefreshToken存库,AccessToken无状态
分布式集群 需要Redis共享Session,架构复杂 天然分布式友好,微服务首选
跨域/多端 同源限制,APP/小程序兼容差 无跨域限制,全端通用
前端存储 浏览器自动管理,无JS操作 前端手动存储,手动添加请求头
强制下线 立即生效,直接删除Session 无法立刻失效AccessToken,依赖RefreshToken销毁
数据安全性 用户数据存在服务端,前端仅ID 用户信息明文编码在Token,不可存敏感字段
XSS风险 HttpOnly Cookie可完全规避窃取 localStorage存AccessToken易被XSS盗取
CSRF风险 存在,必须额外实现CSRF Token 无CSRF风险(Header手动携带,不会自动跨站携带)
请求体积 SessionID很短,开销小 JWT字符串长,带宽消耗更大
开发复杂度 后端简单,前端零逻辑 前端需封装拦截、刷新逻辑,复杂度更高

四、生产环境选型建议

  1. 传统服务端渲染、单体后台、内网系统 → Cookie-Session + CSRF
  2. 前后端分离、小程序、APP、微服务、跨域项目 → JWT Access + Refresh Token
  3. 金融、高安全管控系统(需要实时踢人):两种方案均可,优先Redis自定义短Token(兼顾可控与跨端)
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容