小明最近开发了一个旅游网站,每天有很多用户访问。但他发现了一个问题:
用户登录后,刷新一下页面就得重新登录?!
他百思不得其解,为什么网站不能记住用户的登录状态?
这时,他的师兄告诉他:
“这是因为 HTTP 是无状态的,每次请求都是全新的,服务器根本不知道你是谁。”
小明恍然大悟,但随之而来的新问题是——如何让服务器记住用户的身份呢?
师兄介绍了第一种解决方案:Cookie。
Cookie 是存储在浏览器中的一小段数据,它可以在每次请求时自动携带到服务器,让服务器识别用户身份。
小明的实现方式:
用户登录成功后,服务器生成一个 Set-Cookie
响应头,把用户身份信息存到 Cookie 里:
Set-Cookie: user=12345; Expires=Wed, 21 Oct 2025 07:28:00 GMT
之后每次请求,浏览器都会自动带上 Cookie:
Cookie: user=12345
服务器检查 user=12345
,发现是小明,返回登录后的页面。
Cookie 的优点:
www.example.com
和 api.example.com
共享 Cookie)。⚠️ 但 Cookie 有几个明显的缺陷:
HttpOnly
限制 JS 访问)。小明想了想,发现 Cookie 存在安全性问题,不太适合存储敏感信息,比如登录凭证。于是,他又去了解新的方案。
师兄又介绍了另一种方案:Session。
Session 通过在服务器端存储用户信息,并用一个唯一的 Session ID
让用户“自报家门”。
小明的实现方式:
用户登录成功后,服务器生成一个Session ID(如abc123
),并存储用户信息:
session.setAttribute("user", "小明");
服务器通过 Set-Cookie
把 Session ID
发送给浏览器:
Set-Cookie: session_id=abc123; HttpOnly
之后用户的请求会带上 session_id=abc123
,服务器查找对应的用户信息,返回登录页面。
Session 的优点:
⚠️ 但也有缺点:
小明发现,Session 解决了 Cookie 的安全问题,但如果用户量大,Session 可能会占用太多服务器资源。
于是,他又去探索更轻量级的身份认证方案。
这时,小明听说了一种无状态的身份认证方式——JWT(JSON Web Token)。
JWT 是一种基于 Token(令牌)的身份认证机制,用户登录后,服务器返回一个加密的 Token,之后用户只需带上这个 Token 进行身份认证,服务器不需要存储 Session。
小明的实现方式:
用户登录成功后,服务器生成一个 JWT Token:
{
"userId": 12345,
"exp": "2025-12-31T23:59:59Z"
}
服务器用 密钥 对它进行加密并返回给用户:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsIn...
之后用户每次请求时,把 JWT 放入 Authorization
头里:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsIn...
服务器用密钥解密 JWT,验证其有效性,然后解析出 userId=12345
,继续处理请求。
JWT 的优点:
Authorization
头里,跨域传输。⚠️ 但 JWT 也有缺点:
小明发现,JWT 适合无状态的微服务架构,但如果只是在单体应用里,Session 可能更适合。
方案 | 存储位置 | 适用场景 | 安全性 | 服务器压力 | 是否支持跨域 |
---|---|---|---|---|---|
Cookie | 客户端 | 轻量级存储,如用户偏好 | ❌ 易被篡改 | ✅ 低 | ⚠️ 受 Same-Origin 限制 |
Session | 服务器 | 传统 Web 应用,单体架构 | ✅ 安全 | ❌ 高(需存 Session) | ❌ 不能跨域 |
JWT | 客户端 | 分布式系统、微服务 | ⚠️ 需保护 Token | ✅ 低(无状态) | ✅ 支持 |
小明终于明白了:
他兴奋地优化了自己的旅游网站,并根据需求选择了合适的身份认证方式。
✅ HTTP 是无状态的,需要额外机制记住用户身份。
✅ Cookie 存储在客户端,适用于轻量级数据存储,但不适合存敏感信息。
✅ Session 存储在服务器,更安全,但占用资源,不支持跨域。
✅ JWT 是无状态的 Token 认证方式,适用于分布式系统,但需要妥善管理 Token。
博客主页: 总是学不会.