一文理清Session,Cookie和Token

Eolink开发者社区
企业官方账号
2021-09-09 16:19:32

一文理清Session,Cookie和Token

前言

之前看了不少同类型的文章,对于Cookie和Session真是众说纷纭,有的人说先有Cookie才有Session,也有的人说现有Session再有Cookie。我也说说我的理解,希望对大家有所帮助。

注:需要读者对于Cookie/Session/Token有基本的了解。

Cookie和Session

说这俩之前,先说http,它是一个无状态协议。

怎么理解呢?就是说连续的两次请求之间是没有任何关联的。这样的好处是快速,坏处是想要把同个域名下的两个页面关联起来,必须使用某些手段和工具。

这就引出了我们要说的Cookie和Session。

让我们用文字+图片了解一下客户端访问服务器的流程:

  • 首先,客户端会发送一个http请求到服务器端;
  • 服务器端接受客户端请求后,建立一个Session,并发送一个http响应到客户端,这个响应头,其中就包含Set-Cookie头部。该头部包含了SessionId;
  • 在客户端发起的第二次请求,假如服务器给了Set-Cookie,浏览器会自动在请求头中添加Cookie;
  • 服务器接收请求,分解Cookie,验证信息,核对成功后返回response给客户端

这里有几点要注意的:

  • Cookie只是实现Session的其中一种方案。虽然是最常用的,但并不是唯一的方法。禁用Cookie后还有其他方法存储,比如放在url中;
  • 单一使用Session不用Cookie,或者反过来只用Cookie不用Session,在理论上都可以保持会话状态,只是实际操作中因为多种原因,大多都是Session + Cookie;
  • 用Session只需要在客户端保存一个id,实际上大量数据都是保存在服务器端。如果全部用Cookie,数据量大的时候客户端是没有那么多空间的;
  • 如果只用Cookie不用Session,那么账户信息全部保存在客户端,一旦被劫持,全部信息都会泄露。并且客户端数据量变大,网络传输的数据量也会变大。

 

简单总结,就是Session 有点像用户信息档案表, 里面包含了用户的认证信息和登录状态等信息,而 Cookie 就是用户通行证。

 

Token

Token 也称作令牌,由uid+time+sign(+固定参数)组成:

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

Token 的认证方式类似于临时的证书签名, 并且是一种服务器端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务器端并不会保存身份认证相关的数据。

Token在客户端一般存放于LocalStorage,Cookie,或SessionStorage中。在服务器一般存于数据库中。

 

Token认证流程

Token 的认证流程与Cookie很接近

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

 

 

Cookie,Session和Token的区别

Token可以抵抗CSRF攻击,Cookie+Session不行

我们假设一个场景:

用户正在登陆银行网页,同时登陆了攻击者Tom的网页;

银行网页未对CSRF攻击进行防护;

Tom在网页放了一个表单,该表单提交src为http://www.bank.com/api/transfer,body为count=1000&to=Tom。

如果用的是Session+Cookie,用户打开网页的时候就已经被Tom转走卡里的钱了。因为form 发起的post请求并不受到浏览器同源策略的限制,因此可以任意地使用其他域的 Cookie 向其他域发送 post 请求,形成 CSRF 攻击。在post请求的瞬间,Cookie会被浏览器自动添加到请求头中。

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

 

分布式情况下的Session和Token

我们已经知道Session是有状态的,一般存于服务器内存或硬盘中,当服务器采用分布式或集群时,Session就会面对负载均衡问题。

  • 负载均衡多服务器的情况,不好确认当前用户是否登录,因为多服务器不共享Session。这个问题也可以将Session存在一个服务器中来解决,但是就不能完全达到负载均衡的效果。有办法解决但是挺麻烦的。

而Token是无状态的,Token字符串里就保存了所有的用户信息

  • 客户端登陆传递信息给服务器端,服务器端收到后把用户信息加密(Token)传给客户端,客户端将Token存放于LocalStroage等容器中。客户端每次访问都传递Token,服务器端解密Token,就知道这个用户是谁了。通过cpu加解密,服务器端就不需要存储Session占用存储空间,就很好的解决负载均衡多服务器的问题了。

注:这个方法叫做JWT(Json Web Token)。

 

总结

  • Cookie类似一个令牌,装有SessionId,存储在客户端,浏览器通常会自动添加。
  • Session存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号SessionId,通常存放于Cookie中。服务器收到Cookie后解析出SessionId,再去Session列表中查找,才能找到相应Session。同时Session依赖Cookie。
  • Token可以说是一个无状态的令牌,需要开发者手动添加。用户信息被加密到Token字符串中,服务器收到Token后解密就可知道是哪个用户。
  • JWT只是一个跨域认证的方案。

撰写

Eolinker:致力于API全生命周期开发管理的国产流行API工具。

参考文章

Cookie、Session、Token那点事儿

cookie,token验证的区别

有了cookie为什么需要session

彻底弄懂session,cookie,token

CSRF Token的设计是否有其必要性

cookie,token,session三者的问题和解决方案

负载均衡集群中的session解决方案

JWT介绍

Json Web Token 入门教程

 

 

 

...全文
9048 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

621

社区成员

发帖
与我相关
我的任务
社区描述
API Easy and Open for you
测试工具运维前端 个人社区
社区管理员
  • Eolink
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧