Cookie
简介
Cookie 是由服务器生成,发送给浏览器,浏览器把 Cookie 以 kv 形式保存到本地。浏览器每次向服务器发出请求,就会自动附上这段信息。每个 Cookie 的大小一般不能超过 4KB,一个 web 站点最多可以设置 20 个 Cookie,一个浏览器最多可以设置 300 个 Cookie。同时 Cookie 也具有时效性,超过设置的时效,系统就会自动清除。
用途
会话管理:记录用户的登录状态,访问状态(例如导航,用户的注册流程等);
个性化信息:记忆用户相关的信息(例如记忆上一次登录的用户的 QQ 号码)和用户自定义的一些功能(例如 google 将搜索设置:使用语言、每页的条数等,保存在一个 COOKIE 里);
记录用户的行为:最典型的是公司的 TCSS 系统。它使用 Cookie 来记录用户的点击流和某个产品或商业行为的操作率和流失率。
缺点
Cookie 会被附加在每个 HTTP 请求中,所以无形中增加了流量;
由于在 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题,除非用 HTTPS;
Cookie 的大小限制在 4KB 左右,对于复杂的存储需求来说是不够用的。
Session
Session 就是“会话”,当用户打开某个 web 应用时,便与 web 服务器产生一次 session。服务器使用 session 把用户的信息临时保存在了服务器上,用户离开网站后 session 会被销毁,相对 cookie 更安全。
cookie 和 session 执行流程
客户端发送一个 http 请求到服务器端;
服务器端接受客户端请求后,建立一个 session,并生成 sessionID 设置进 Cookie 头并发送一个 http 响应到客户端;
在客户端发起的第二次请求,假如服务器给了 set-Cookie,浏览器会自动在请求头中添加 cookie;
服务器接收请求,分解 cookie,验证信息,核对成功后返回 response 给客户端
Session 和 Cookie 一般都是结合使用的。用 session 只需要在客户端保存一个 id,实际上大量数据都是保存在服务端,所以当访问增多,session 会比较占用服务器的性能。简而言之, 将登陆信息等重要信息存放为 session,其他信息如果需要保留,可以放在 cookie 中。
Token
token 也称作令牌,由 uid+time+sign[+ 固定参数]。token 的认证方式类似于临时的证书签名, 并且是一种服务端无状态的认证方式, 所谓无状态就是服务端并不会保存身份认证相关的数据。
uid: 用户唯一身份标识;
time: 当前时间的时间戳;
sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接;
固定参数 (可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库。
token 在客户端一般存放于 localStorage,cookie,或 sessionStorage 中。token 认证流程:
用户登录,成功后服务器返回 Token 给客户端;
客户端收到数据后保存在客户端;
客户端再次访问服务器,将 token 放入 headers 中;
服务器端采用 filter 过滤器校验。校验成功则返回请求数据,校验失败则返回错误码。
token 可以抵抗 csrf,cookie+session 不行
假如用户正在登陆银行网页,同时登陆了攻击者的网页,并且银行网页未对 csrf 攻击进行防护。攻击者就可以在网页放一个表单,该表单提交 src 为 http://www.bank.com/api/transfer,body 为 count=1000&to=Tom。倘若是 session+cookie,用户打开网页的时候就已经转给 Tom1000 元了. 因为 form 发起的 POST 请求并不受到浏览器同源策略的限制,因此可以任意地使用其他域的 Cookie 向其他域发送 POST 请求,形成 CSRF 攻击。在 post 请求的瞬间,cookie 会被浏览器自动添加到请求头中。但 token 不同,token 是开发者为了防范 csrf 而特别设计的令牌,浏览器不会自动添加到 headers 里,攻击者也无法访问用户的 token,所以提交的表单无法通过服务器过滤,也就无法形成攻击。
分布式情况下的 session 和 token
我们已经知道 session 时有状态的,一般存于服务器内存或硬盘中,当服务器采用分布式或集群时,session 就会面对负载均衡问题。
负载均衡多服务器的情况,不好确认当前用户是否登录,因为多服务器不共享 session。这个问题也可以将 session 存在一个服务器中来解决,但是就不能完全达到负载均衡的效果。当今的几种解决 session 负载均衡的方法。
而 token 是无状态的,token 字符串里就保存了所有的用户信息
客户端登陆传递信息给服务端,服务端收到后把用户信息加密(token)传给客户端,客户端将 token 存放于 localStroage 等容器中。客户端每次访问都传递 token,服务端解密 token,就知道这个用户是谁了。通过 cpu 加解密,服务端就不需要存储 session 占用存储空间,就很好的解决负载均衡多服务器的问题了。这个方法叫做 JWT(Json Web Token)
总结
session 存储于服务器,可以理解为一个状态列表,拥有一个唯一识别符号 sessionId,通常存放于 cookie 中。服务器收到 cookie 后解析出 sessionId,再去 session 列表中查找,才能找到相应 session。依赖 cookie
cookie 类似一个令牌,装有 sessionId,存储在客户端,浏览器通常会自动添加。
token 也类似一个令牌,无状态,用户信息都被加密到 token 中,服务器收到 token 后解密就可知道是哪个用户。需要开发者手动添加。
jwt 只是一个跨域认证的方案
原文地址:彻底弄懂 session,cookie,token