Cookie,Session 和 Token 究竟是怎么个关系?

文章介绍了Cookie、Session和Token在网络应用中作为用户身份验证的机制,分析了它们的工作原理、优缺点以及应用场景。Cookie由服务器发送到浏览器并存储,Session依赖服务器存储用户状态,而Token提供了一种减少服务器存储负担的验证方式。Token机制在分布式系统和安全性方面更具优势。

以前,我一直搞不清楚 Cookie,Session 和 Token 之间的关系,看了知乎上的这篇文章才懂得了:网络应用中session和token本质是一样的吗,有什么区别?

为了避免用户频繁的登录,所以需要一种方式来记录用户登录信息。Cookie、Session 和 Token 就是为了解决这个问题,发展出来的三种解决方案。

Cookie

Cookie 是服务器创建的,通过在相应头中的 Set-Cookie 选项,发送到用户浏览器。浏览器会将接收到的 Cookie 保存在本地,并且会在下次向同一个服务器发送请求时,通过 Cookie 请求头携带上当前保存的 Cookie。

另外,Cookie 的过期时间、域、路径、有效期、适用站点都可以根据需要来指定。

Cookie 在被用于实现交互状态时,存在的问题有:

  1. 潜在的网络攻击,比如:被劫持、跨站请求伪造(CSRF:Cross-site request forgery)
  2. 网络负载高,每次都要发送很多额外的信息
  3. 数量和容量有限

Session

Session 机制是:服务器生成一个唯一的 SessionID 发送的客户端,客户端在之后请求资源时携带上 SessionID 信息,服务器和客户端就通过 SessionID 进行身份识别。同时,服务器负责存储客户端的状态信息,通常保存在内存(RAM)中,避免了重复的信息传输。

那客户端的 SessionID 信息是怎么存储呢?首选方式是存储在 Cookie 中,也可以通过 URL 重写的方式进行传输。

Session和Cookie的关系就像加班和加班费的关系,看似关系很密切,实际上没啥关系。

Session 存在的问题:

  1. 服务器的存储压力较大(用户信息通常是存储在 RAM 中的)
  2. 分布式系统的信息共享问题

Token

Token 是由服务生成并发送给客户端的令牌,令牌中记录了产生令牌时用的加密算法、客户信息、经过秘钥生成的 sign。客户端将接收到的令牌保存在本地,以后每次请求时都要携带上。服务器接收到 Token 时,解析关键信息,再经过相同的加密算法、客户信息,重新生成一次 sign,然后和客户端发送的 sign 进行对比,一致则认为是有效的,否则拒绝服务。

Token 机制可以避免服务器存储海量的用户登录信息,实现了通过 CPU 加解密的时间换取存储空间(Session 信息一般是存储在内存当中的)。

七牛云使用 Token 的实例

存储在七牛云上的私有资源,当用户想对指定的资源公开一段时间时是如何实现的呢?

在用户登录 Kodo Browser(七牛对象存储提供的图形化管理工具)时,需要提供 AccessKeyId 和 AccessKeySecret。当用户想公开一段时间私有资源时,通过以下步骤生成一个 URL 就可以了:

  1. 在资源的 URL 中拼接上 AccessKeyId,用来标记当前的用户;
  2. 在资源的 URL 中拼接上设置的公开时间;
  3. 通过约定的算法,使用 AccessKeySecret 对 AccessKeyId 和公开时间进行加密生成 sign,并拼接到 URL 上。

当七牛的服务器收到访问请求时,提取出 AccessKeyId 和公开时间,并通过 AccessKeyId 来获取对应的 AccessKeySecret,通过相同的算法计算 sign,如果计算的 sign 值和 URL 中的 sign 值相同,则提供资源信息。

这样就实现了客户在将私有信息设置为公开时,并不需要经过服务器,服务器更不会存储资源的公开信息。

注意:以上过程时凭记忆总结的,可能会有偏差。

总结

Cookie 侧重于客户端对信息的存储行为,Session 和 Token 侧重于服务端用于身份验证的行为。

### Cookie Cookie 是由服务器送给客户端的一小段数据,客户端会将其保存,并在后续请求中携带回服务器。它通常用于记录用户状态、偏好设置等信息。Cookie 可以设置过期时间,根据是否设置过期时间分为会话 Cookie 持久 Cookie。会话 Cookie 在浏览器关闭时自动清除,而持久 Cookie 则会在指定的时间后过期[^1]。 ### Session Session服务器端用来跟踪用户状态的一种机制。当用户登录后,服务器会创建一个唯一的 Session ID,并将该 ID 通过 Cookie 或 URL 重写等方式返回给客户端客户端在后续请求中携带这个 Session ID,服务器通过查找存储的 Session 数据来识别用户状态。Session 的生命周期通常由服务器控制,可以灵活地设置过期时间或手动销毁[^1]。 ### Token Token 是一种无状态的身份验证机制。用户登录后,服务器生成一个 Token 并返回给客户端客户端在后续请求中携带该 Token服务器通过解析 Token 来验证用户身份。与 Session 不同的是,Token 本身可能包含用户信息(如用户名、权限等),服务器无需查询数据库即可完成验证。Token 的生命周期由签发时设定的有效期决定,且一旦签发,在有效期内无法被撤销[^2]。 ### JWT (JSON Web Token) JWT 是 Token 的一种具体实现,采用 JSON 格式定义声明(claims),并通过签名确保数据的完整性。JWT 由三部分组成:头部(Header)、载荷(Payload)签名(Signature)。其中,Payload 包含了用户信息(如用户 ID、角色等),签名则用于验证 JWT 的真实性。JWT 是无状态的,服务器不需要存储任何 Session 数据,只需使用密钥解密 JWT 即可验证其有效性。这种方式使得 JWT 非常适合分布式系统中的身份验证需求[^4]。 ### 区别与适用场景 - **状态管理方式** Cookie客户端存储的小型数据,Session服务器端的状态管理机制,Token JWT 则是无状态的身份验证机制。Session 需要服务器维护状态,而 Token JWT 不需要。 - **安全性** Cookie 可以通过设置 `HttpOnly` `Secure` 属性提高安全性,防止 XSS 攻击。Session 依赖于 Cookie 存储 Session ID,因此也面临类似的安全风险。Token JWT 由于是无状态的,更容易防范 CSRF 攻击,但需要注意 Token 的保护,避免泄露[^2]。 - **扩展性** Session 在分布式系统中需要额外的机制(如 Redis)来共享状态,增加了复杂度。Token JWT 更容易扩展,尤其是 JWT,因为服务器不需要存储任何状态信息,只需验证签名即可[^3]。 - **生命周期控制** Session 可以通过编程方式随时销毁,而 Token JWT 一旦签发,在有效期内无法被撤销。如果需要提前失效 Token 或 JWT,必须引入黑名单机制或其他额外逻辑[^3]。 - **性能影响** Session 每次请求都需要查询数据库或缓存获取用户信息,增加了 I/O 开销。Token JWT 尤其是 JWT,由于自包含用户信息,减少了数据库查询次数,提升了性能[^4]。 ### 示例代码 以下是一个简单的 JWT 签发与验证的 Python 示例: ```python import jwt from datetime import datetime, timedelta # 密钥 SECRET_KEY = 'your-secret-key' # 签发 JWT def generate_jwt(user_id): payload = { 'user_id': user_id, 'exp': datetime.utcnow() + timedelta(hours=1) # 设置过期时间为1小时后 } token = jwt.encode(payload, SECRET_KEY, algorithm='HS256') return token # 验证 JWT def verify_jwt(token): try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return payload['user_id'] except jwt.ExpiredSignatureError: return 'Token 已过期' except jwt.InvalidTokenError: return '无效的 Token' # 使用示例 token = generate_jwt(123) print("Generated JWT:", token) user_id = verify_jwt(token) print("Verified User ID:", user_id) ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值