JS-前端登录状态保持:Cookie+Session vs Token

49 阅读4分钟

前言

HTTP 协议本身是无状态的,这意味着服务器无法自动识别两次请求是否来自同一个用户。为了实现“登录状态保持”,前端开发中主要有两种主流方案:传统的 Cookie + Session 模式和现代的 Token (主要是 JWT) 模式。本文将带你深入剖析两者的原理、区别及应用场景。

一、 传统方案:Cookie + Session

这是最经典的解决方案,核心在于“服务端存储”。

1. 实现原理

  1. 登录:用户发送账号密码,服务器验证通过。
  2. 创建 Session:服务器在内存(或 Redis)中创建一个 Session 对象,存储用户信息,并生成一个唯一的 SessionID
  3. 返回 Cookie:服务器将 SessionID 写入 HTTP 响应头的 Set-Cookie 字段中。
  4. 保持状态:浏览器收到响应后自动将 Cookie 存入本地。下次请求时,浏览器会自动携带包含 SessionID 的 Cookie。
  5. 校验:服务器解析 Cookie 中的 SessionID,去内存中查找对应的 Session 对象,从而确定用户身份。

2. 优缺点分析

  • 优点

    • 技术成熟,框架支持度高(如 Java 的 JSESSIONID)。
    • 控制力强(服务器可以随时废弃某个 SessionID 实现强制下线)。
  • 缺点

    • 服务器压力大:每个在线用户都需要占用服务器内存,用户量大时开销巨大。
    • 扩展性差(集群问题) :在多台服务器集群下,需要解决“Session 共享”问题(通常需引入 Redis),否则用户在这个服务器登录,下一次请求到了另一台服务器就失效了。
    • 移动端限制:原生 APP(Android/iOS)对 Cookie 的支持不如浏览器友好,处理起来较麻烦。
    • CSRF 风险:基于 Cookie 的自动发送机制,容易遭受跨站请求伪造攻击。

二、 现代方案:Token (以 JWT 为主)

随着前后端分离和移动互联的发展,Token(令牌)技术逐渐成为主流,尤其是 JWT (JSON Web Token) 。它的核心在于“时间换空间”,服务器不再存储登录状态。

1. 实现原理

  1. 登录:用户发送账号密码,服务器验证通过。
  2. 生成 Token:服务器使用一套加密算法(如 HMACSHA256)和密钥,将用户信息(如 UserID、权限)签名生成一个字符串(Token)。注意:服务器不存储这个 Token。
  3. 返回 Token:服务器将 Token 返回给客户端。
  4. 存储与携带:客户端(浏览器/APP)将 Token 存储在 localStoragesessionStorageCookie 中。下次请求时,通常将 Token 放入 HTTP 请求头的 Authorization 字段中(格式:Bearer <token>)。
  5. 校验:服务器收到请求后,用相同的密钥和算法解密/校验签名。如果签名匹配且未过期,即认为合法。

2. 核心优势

  • 无状态 (Stateless) :服务器不需要存储 Session,极大降低了服务器内存压力。
  • 支持集群:只要所有服务器使用相同的密钥(Secret),无论请求打到哪台服务器都能通过校验,天生支持分布式架构。
  • 跨平台/跨域:非常适合移动端 APP、小程序以及前后端分离的跨域场景。
  • 性能高:解析 Token 的计算时间通常远小于查询数据库或 Redis 的时间。

三、 Token 的结构解密

一个标准的 Token(如 JWT)通常由三部分组成,中间用 . 分隔:

Header.Payload.Signature

1. 关键字段说明

  • Header (头部) :声明类型(JWT)和加密算法(如 HS256)。

  • Payload (负载) :存放有效信息(注意:这里的信息虽然经过 Base64 编码但未加密,任何人都能解码看到,所以不要放密码等敏感信息)。

    • 用户标识 (sub/uid) :User ID,用户的唯一标识。
    • 权限/角色 (scope/role) :标识该用户是管理员还是普通用户。
    • 过期时间 (exp) :Expiration Time,Token 何时失效。
    • 签发时间 (iat) :Issued At,Token 是什么时候生成的。
  • Signature (签名) :这是最关键的部分。服务器用密钥对 Header 和 Payload 进行签名。如果攻击者修改了 Payload 里的权限,签名校验就会失败。


四、 总结:如何选择?

维度Cookie + SessionToken (JWT)
状态存储服务端(内存/数据库)客户端(自身携带信息)
服务器压力高(占内存)低(仅需 CPU 计算)
分布式支持需配合 Redis 做 Session 共享天生支持
客户端支持浏览器友好,APP 较差全平台通用
安全性防 CSRF 需额外处理需防 XSS(若存 localStorage)
注销机制容易(服务端删除 Session)较难(需配合黑名单机制)

面试建议:

如果面试官问“Token 安全吗?”,一定要回答:Token (JWT) 的 Payload 部分默认只是 Base64 编码,不是加密,所以不能存敏感数据。它的安全性在于签名,保证数据不被篡改。