登录系统的Cookie和Session和JWT和OAuth
登录系统全链路解析:Cookie/Session/JWT/OAuth/双令牌登录 原理与落地
摘要
本文详细解析了Web登录系统的全链路技术演进,从最基础的Cookie/Session有状态会话机制,到无状态的JWT令牌方案,再到解决第三方授权痛点的OAuth2.0开放标准,最终落地到企业级生产环境的双令牌登录架构。文章深入拆解了各方案的核心原理、完整执行流程、优缺点与适用场景,补充了生产环境的安全落地规范,并附全方案对比整理表格,帮助开发者从零到一吃透登录系统的底层逻辑与选型规则。
一、登录系统的核心本质
所有登录技术的诞生,都源于HTTP协议的无状态特性:HTTP协议的每一次请求都是完全独立的,服务器无法识别两次请求是否来自同一个用户。
而登录系统的核心目标,就是给无状态的HTTP请求,加上可识别的用户身份标记,让服务器能持续确认「你是谁」,所有的Cookie、Session、JWT等技术,都是围绕这个核心目标设计的身份标记方案。
二、基础会话机制:Cookie与Session
Cookie与Session是Web开发最经典的会话方案,也是所有登录技术的基础,二者相互配合完成用户身份识别。
2.1 核心定义
- Cookie:浏览器存储的小型文本文件,由服务器通过
Set-Cookie响应头下发给浏览器,浏览器后续对该域名的请求,会自动携带对应的Cookie,分为关闭浏览器就失效的会话Cookie,和设置了过期时间的持久Cookie。 - Session:服务器端存储的用户会话对象,每个Session对应一个全局唯一的
SessionId,服务器通过SessionId匹配对应的用户会话,获取用户身份信息。
2.2 完整执行流程

易混淆点:
-
浏览器发起 HTTP 请求(图中步骤 1)
- 客户端(浏览器)发送一个 HTTP 请求(比如
GET /login)。 - 这个请求包含 URL、Header(如 Cookie)、Body 等原始数据。
- 客户端(浏览器)发送一个 HTTP 请求(比如
-
Servlet 容器自动创建 Request 对象
- 关键点:当请求到达服务器(如 Tomcat)时,Servlet 容器(不是您的 Servlet 代码)会自动创建两个核心对象:
HttpServletRequest request:封装 HTTP 请求的所有信息(参数、Header、Cookie 等)。HttpServletResponse response:用于生成响应。
- 这个过程是隐式的:您不需要手动创建
request对象,容器会在调用 Servlet 的doGet()/doPost()方法时,自动将request作为参数传递进来。
程序员只负责“使用”而非“创建”// 示例:Servlet 代码中,request 是容器传入的,不是自己 new 的 protected void doGet(HttpServletRequest request, HttpServletResponse response) { // 此时 request 对象已由容器创建并初始化 request.setAttribute("message", "Hello from Servlet!"); // ✅ 正确:设置属性 } - 您在 Servlet 中操作的是容器已经创建好的
request对象,通过它的方法(如setAttribute)存取数据。 - 不是您“通过 Servlet 创建了 Request 对象”,而是容器预先创建好并交给您使用。
- 关键点:当请求到达服务器(如 Tomcat)时,Servlet 容器(不是您的 Servlet 代码)会自动创建两个核心对象:
流程:
- 用户输入账号密码,提交登录请求
- 服务器校验账号密码无误后,生成专属的Session会话对象,同时生成唯一的
SessionId - 服务器通过响应头
Set-Cookie,将SessionId写入用户浏览器 - 用户后续的所有业务请求,浏览器会自动携带包含
SessionId的Cookie - 服务器接收请求后,通过Cookie中的
SessionId,找到对应的Session会话,确认用户身份 - 用户登出时,服务器删除对应的Session对象,同时通知浏览器清除Cookie,会话失效
2.3 核心特性
- 有状态设计:用户会话数据全部存在服务器端,浏览器只存一个无意义的
SessionId - 安全性高:敏感信息不会泄露到前端,
SessionId泄露后可随时在服务器端作废 - 痛点明显:分布式/集群环境下,存在Session共享问题;移动端APP原生不支持Cookie机制,适配成本高
三、无状态认证方案:JWT令牌
JWT(JSON Web Token)的诞生,核心解决了Cookie/Session在分布式环境下的共享痛点,是前后端分离、微服务架构的主流身份认证方案。
3.1 为什么需要JWT
在集群部署场景下,用户第一次请求落在A服务器,Session存在A服务器;第二次请求被负载均衡转发到B服务器,B服务器没有对应的Session,就会出现用户需要重新登录的问题。
虽然可以通过Redis统一存储Session解决共享问题,但依然是有状态设计,服务器需要持续维护会话数据。而JWT实现了完全无状态,服务器不需要存储任何会话数据。
3.2 JWT核心结构
JWT是一段紧凑、自包含的加密字符串,由三部分组成,用.分隔,完整格式为Header.Payload.Signature:
- Header(头部):声明令牌类型为JWT,以及签名使用的算法(如HS256),经过Base64编码生成
- Payload(载荷):核心数据区,存放用户ID、角色、令牌过期时间等非敏感信息,同样经过Base64编码生成
- Signature(签名):用服务器端私钥,对Header+Payload的内容进行加密生成,核心作用是防篡改,确保令牌内容没有被前端修改
3.3 完整执行流程
- 用户提交账号密码登录,服务器校验身份无误
- 服务器通过私钥,将用户身份信息、过期时间等内容,生成JWT令牌,直接返回给前端
- 前端将JWT存储在本地(localStorage/sessionStorage),后续业务请求时,将JWT放在请求头
Authorization: Bearer <令牌>中携带 - 服务器接收请求后,通过公钥验签,确认令牌未被篡改,同时解析Payload中的用户信息,完成身份认证
- 用户登出时,前端直接删除本地存储的JWT即可
3.4 核心特性
- 无状态设计:令牌本身自包含用户身份信息,服务器不需要存储任何会话数据,集群扩容无压力
- 跨端适配好:天然支持浏览器、移动端APP、小程序等所有终端,不依赖Cookie机制
- 致命痛点:令牌一旦签发,在过期时间内始终有效,服务器无法主动作废,出现令牌泄露、用户改密码、账号被盗等场景时,无法强制下线
四、第三方授权标准:OAuth2.0
OAuth2.0的诞生,解决了跨平台第三方授权的核心痛点,也就是我们常见的「微信一键登录」「QQ登录」「支付宝登录」,这是JWT和Cookie/Session都无法覆盖的场景。
4.1 为什么需要OAuth2.0
如果用户想用微信账号登录B站,用纯JWT/Cookie方案,只能让用户把微信的账号密码交给B站,这会带来致命的安全风险:B站拿到用户微信密码后,可完全操控用户微信账号,一旦数据泄露,用户全平台账号都会受影响。
OAuth2.0的核心价值,就是在不泄露用户账号密码的前提下,让第三方应用有限度地获取用户信息,完成身份认证。
4.2 核心角色
OAuth2.0标准定义了四个核心角色,所有流程都围绕这四个角色展开:
- 资源所有者:最终用户,也就是微信账号的持有者
- 客户端:第三方应用,比如需要微信登录的B站
- 授权服务器:提供身份授权的服务,比如微信的授权服务
- 资源服务器:存储用户信息的服务,比如微信的用户信息接口
4.3 授权码模式完整流程(行业主流)

- 用户点击B站的「微信一键登录」按钮
- B站将页面跳转到微信的授权服务器,同时携带自身的回调地址、权限范围等参数
- 微信授权服务器弹出确认框,询问用户「是否同意授权B站获取你的头像、昵称」
- 用户点击同意,微信授权服务器生成一次性的授权码,通过回调地址返回给B站
- B站后端拿到授权码后,带着授权码去微信授权服务器,申请正式的访问令牌
access_token - 微信授权服务器校验授权码无误后,返回
access_token给B站 - B站拿着
access_token,去微信的资源服务器,获取用户的头像、昵称、唯一ID等信息 - B站拿到用户信息后,完成账号匹配/注册,给前端下发自身业务的登录令牌,完成整个登录流程
4.4 核心特性
- 彻底隔离用户密码:第三方应用全程接触不到用户的主账号密码,安全风险完全隔离
- 权限可控:用户可自主选择授权的信息范围,也可随时在授权服务器取消第三方应用的授权
- 与JWT是搭配关系:OAuth2.0是一套完整的授权流程标准,而JWT是流程中令牌的常用载体,二者不是替代关系,而是互补关系
五、企业级落地架构:双令牌登录
双令牌登录是目前互联网企业生产环境的主流方案,核心解决了纯JWT无法主动作废、泄露风险高的痛点,兼顾了JWT无状态的优势,和有状态方案的安全管控能力。
5.1 核心设计
双令牌指的是Access Token(访问令牌)+ Refresh Token(刷新令牌)的组合方案,二者分工明确,各司其职:
- Access Token:短期有效(通常2小时以内),本质就是JWT令牌,唯一作用是访问业务接口,过期后直接失效
- Refresh Token:长期有效(通常7-30天),只能用来刷新Access Token,无法访问任何业务接口,后端通过Redis维护白名单管控生命周期
Redis---
R
位置问题
客户端-客户端‘+++++secure
客户端-云端redis
5.2 完整执行流程
- 用户提交账号密码登录,服务器校验身份无误
- 服务器签发一对令牌:短期的Access Token + 长期的Refresh Token,同时将Refresh Token的唯一标识存入Redis白名单,设置与令牌一致的过期时间
- 前端拿到两个令牌后,分开安全存储,Access Token放在内存中,Refresh Token放在更安全的加密存储区
- 前端发起业务请求时,携带Access Token,服务器验签通过后,处理业务请求并返回结果
- 当Access Token过期,服务器返回401状态码,前端自动携带Refresh Token,调用令牌刷新接口
- 服务器解析Refresh Token,提取用户ID和令牌唯一标识,去Redis校验白名单是否存在
- 校验通过后,服务器签发新的Access Token + Refresh Token,同时删除Redis中旧的Refresh Token白名单,返回新令牌给前端
- 用户主动登出时,服务器直接删除Redis中对应的Refresh Token白名单,令牌立刻失效,无法再刷新
- 用户修改密码、账号出现异常时,服务器可直接删除该用户所有的Refresh Token白名单,实现全设备强制下线
5.3 核心优势
- 安全兜底:Access Token短期有效,即使泄露,影响窗口极短;Refresh Token有白名单管控,可随时主动作废
- 体验友好:用户不需要频繁重新登录,Refresh Token可无感刷新Access Token
- 兼容分布式:Access Token依然保持无状态特性,不影响集群扩容,仅Refresh Token依赖Redis做轻量管控
- 权限管控灵活:可实现单设备登录、多设备登录、指定设备下线等复杂业务需求
六、全方案对比表(附整理)
| 认证方案 | 核心原理 | 有无状态 | 核心优势 | 核心缺点 | 适用场景 |
|---|---|---|---|---|---|
| Cookie+Session | 服务器存会话,浏览器存SessionId做匹配 | 有状态 | 安全性高、敏感信息不外露、可随时作废会话 | 分布式环境有共享痛点、移动端适配差 | 传统单体项目、纯PC端管理后台 |
| 纯JWT | 令牌自包含身份信息,服务器验签完成认证 | 无状态 | 天然适配分布式、跨端兼容性好、扩容无压力 | 签发后无法主动作废、泄露风险高 | 纯前端无状态项目、内部低风险系统、短期有效接口认证 |
| OAuth2.0 | 第三方授权标准,不泄露密码完成身份认证 | 流程无状态,可搭配JWT/ Session | 彻底隔离主账号密码、权限可控、行业通用标准 | 流程复杂、依赖第三方授权服务器 | 第三方一键登录、开放平台API授权、多系统单点登录 |
| 双令牌登录 | Access Token做业务访问,Refresh Token做生命周期管控 | 半有状态 | 兼顾无状态优势与安全管控、可主动作废、体验与安全平衡 | 需要维护Redis白名单、架构复杂度略高 | 互联网生产环境、前后端分离项目、多端适配的商用系统 |
七、生产环境落地安全规范
- 所有认证方案必须配合HTTPS协议,防止令牌、Cookie、账号密码被中间人攻击窃取
- Cookie必须设置
HttpOnly、Secure、SameSite属性,防止XSS攻击窃取Cookie,以及CSRF攻击 - JWT的Payload中严禁存储密码、手机号等敏感信息,Base64编码仅为格式转换,并非加密,可直接解码
- Refresh Token必须通过Redis白名单管控,严禁使用纯无状态的Refresh Token,否则无法实现主动下线
- 登录接口、验证码接口、令牌刷新接口必须做限流处理,防止暴力破解、恶意刷接口攻击
- 令牌过期时间需遵循「最短有效原则」,Access Token有效期越短越安全,Refresh Token需根据业务场景合理设置
- 前端存储令牌需做好加密防护,严禁将令牌明文存储在localStorage中,防止XSS攻击泄露
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)