Cookie:
是服务器发送到浏览器,并保存在客户端的数据; (跨站是不能共享的,在移动端原生请求没有cookie之说,所以移动平台多用token,token是随着header的 Authorization 自定义头里传过来的,可扩展性好)
Session:
是基于Cookie实现的,通常是需要结合Cookie使用,登录后服务器会创建一个特殊的cookie:sessionid(或者叫jsessionid)给浏览器端,并在服务器端保存一个session,每次请求会携带sessionid去服务器端查询session,从而找到userid信息,以区分不同的用户(我们现在核心就是用的这种形式)
如何考虑分布式session问题?
背景:如果存在多台服务器,登录请求到A服务器,A服务器生成了session,但其他服务器是没有session的,如果下次请求携带sessionid到B服务器,此时就找不到session了,就需要重新登录了,针对这种情况,有如下三种解决方式:
1、session复制
A服务器生成session后,复制到其他服务器,缺点:每台服务器都保存了session,保存多份导致数据冗余,如果服务器很多,会造成很大的性能消耗
2、session粘连:
Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象,Ngnix的sticky模块可以支持这种方式,支持按ip或cookie粘连等,如按ip粘连:
upstream tomcats{
ip_hash;
server 10.1.1.107:88;
server 10.1.1.132:80;
}
3、session共享
这种方式也是目前大公司普遍采用的方案,将session保存在redis,memcached等中间件,请求到来时,各个机器去这些中间件去一下session即可。但是这种方式每次请求都要去redis取一下session,多了一次内部链接,消耗了部分性能,另外为了保证redis的高可用,必须做集群。
Token:
类似于Cookie,但又不同于Cookie,token是服务器端返回给浏览器的,只存储在浏览器端,服务器端不做存储;Token是一串加密后的字符串,通常使用uid、时间戳、签名以及一些其他参数组成;token多用于APP客户端和服务器交互的模式;(渠道用的这种形式)
当 server 收到浏览器传过来的 token 时,它会首先取出 token 中的 header + payload,根据密钥生成签名,然后再与 token 中的签名比对,如果成功则说明签名是合法的,即 token 是合法的。而且你会发现 payload 中存有我们的 userId,所以拿到 token 后直接在 payload 中就可获取 userid,避免了像 session 那样要从 redis 去取的开销
另外需要注意的是 token 一般是放在 header 的 Authorization 自定义头里,不是放在 Cookie 里的,这主要是为了解决跨域不能共享 Cookie 的问题
三者区别:
总结下来就是:session 是空间换时间,token 是时间换空间。