# 12. Cookie、Session、Token区别

# http是无状态的协议

HTTP是一种不保存状态的,无状态的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,自身不具备保存之前发送过的请求或响应信息的功能。每当有新的请求发送时,就会有对应的新响应产生。这是为了快速的处理大量事务,确保协议的可伸缩性。

至于为什么HTTP没状态,可能是因为HTTP协议设计时一是为了简单考虑二是早期没考虑到现在web发展需求这个情况。

HTTP/1.1虽然是无状态协议,但为了实现保持状态功能,于是引入了Cookie技术。

如果只用Cookie来识别用户状态,那么用户信息会全部保存在客户端,虽然也可以实现服务器识别用户状态,但会造成以下问题:

  1. 可能造成CSRF安全问题,一旦数据泄露,那么攻击者就可以伪造用户做一些危险操作。
  2. Cookie只有4k容量,数据量大时可能会造成空间不足,而且网络传输的数据量也会变大。

# Session

因为Cookie非常容易造成安全问题,所以就有了Session+Cookie。过程如下:

  1. 客户端登录时发送请求
  2. 服务端接收到请求验证登录通过后,建立一个sessionid随机字符串。并在响应头字段Set-Cookie中返回sessionId。Set-Cookie格式如下
Set-Cookie: sessionId:xxx
1
  1. 客户端再次发送请求时浏览器会自动在Cookie中包含sessionid发送到服务端。
  2. 服务端接收到请求后对比sessionid,然后获取到用户信息。

Session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。禁用Cookie后还有其他方法存储,比如放在url中。会出现以下问题:

  1. 造成CSRF安全问题
  2. 用户信息全部放在服务端会造成服务器压力

# Token

因为Session+Cookie的方式会造成安全问题和可能会造成服务器压力过大的问题,就有了token。token 也称作令牌。服务端并不会保存身份认证相关的数据。

# 组成

uid: 用户唯一身份标识
time: 当前时间的时间戳
sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接
固定参数(可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库

# 存放

token在客户端一般存放于localStorage,cookie,或sessionStorage中。在服务器一般存于数据库中。

# 认证流程

token 的认证流程与cookie很相似

  1. 用户登录,成功后服务器返回Token给客户端。
  2. 客户端收到数据后保存在客户端
  3. 客户端再次访问服务器,将token放入headers中
  4. 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

token是开发者为了防范csrf而特别设计的令牌,浏览器不会自动添加到headers里,攻击者也无法访问用户的token,所以提交的表单无法通过服务器过滤,也就无法形成攻击。

# 参考

https://segmentfault.com/a/1190000017831088