这是我参与11月更文挑战的第7天,活动详情查看:2021最后一次更文挑战
先交代一下背景,http 本身是一个无状态协议,即请求与请求之间没有任何关系。这在 web1.0 网页只有浏览需求的年代,还没啥问题。但是到了 web2.0,网页更注重交互,服务器需要知道发送请求的用户有没有登陆、购物车里有几件商品,http 协议无状态问题就很大了。但是好在 http 是一个拓展性很强的协议,http 标准就新增了了 cookie 相关的一系列 http header 用来解决没有状态的问题。
Cookie
cookie 的流程是这样的,服务端通过 set-cookie 通知浏览器将服务器的信息存储到浏览器 cookie,后续浏览器往相同服务发送的请求会自动把之前存储的 cookie 自动带上,这样就解决了 http 无状态的问题。
如果需要跨域带 cookie 的话,需要服务端设置:
Access-Control-Allow-Credentials:true;
Allow-Control-Allow-Origin:" //服务器接受请求的域名"(此时不可用*通配符,且只能指定单一域名);
如果 cookie 存在一级域名下,那么该域名下的二级、三级、N级域名,都可读取到该 cookie,但是无法清楚该 cookie。
Session
那么 Session 是什么,Session 和 Cookie 解决的都是同一个问题,只不过 Cookie 主要在浏览器即客户端生效,Session 是用在服务器端。
前面介绍 Cookie 的时候说到浏览器将服务端的信息存储到了浏览器 Cookie,这个服务端的信息在 Session 认证场景下通常是指 SessionId,SessionId 是服务端生成的身份信息 key-value 对的 key,value 是用户的身份信息,即通过 SessionId 可以定位到用户的身份。
Session 存在生命周期,通常是用户登陆完成后生成 Session 信息,用户退出登陆/登陆过期清除 Session。
可以想象,Session 需要客户端维护一个 Session 列表,这就引出了两个问题,第一个是用户数量大会有很大的资源开销;另外一个是多机器 Session 同步的问题。即使采用了单独的机器维护 Session,也会考虑单点故障的问题。一句话,成本较高,Token 就是为了解决 Session 存在的问题。
Token
JSON Web Token 换了另外一种思路,将身份信息存储到了客户端,通过加密验签的方式来确保客户端的身份信息合法。这样服务器只需要运行统一的程序,不需要维护统一的数据,从而使服务可以无压力横向扩展,同时与 Cookie 解除了强绑定也规避了 CSRF 问题。
通常我们做多点登陆的时候,也是采用验证 token 的方式,去建立多个站点用户登录的连接。旧站点的用户带着它的 token 值去访问新的站点,可以实现多点登陆。