session和token的区别

通过讲述保持会话状态方式的演变过程,来讲述session和token的区别:

1、很久很久以前,Web 基本上就是文档的浏览而已,服务器不用记住是哪个浏览器刚刚发送了HTTP请求, 每个请求对服务器来说都是全新的。

2、但是随着交互式Web应用的兴起,像在线购物网站,需要登录的网站等;服务器就要记录哪些人登录了系统,让已经登录了系统的用户再次发送请求时,不必再次登录;这就要管理会话,但这是一个不小的挑战,因为HTTP请求是无状态的;所以想出的办法就是在服务器端产生一个session对象,用来保存此次请求的信息,同时给浏览器返回一个会话标识(session id), 说白了就是一个随机的字串;然后当此浏览器再次向服务器发起HTTP请求的时候,把这个会话标识一并捎过来,这样服务器就能区分这次请求和上次请求是同一个浏览器发送的。

3、在这种情况下,浏览器只需要保存服务器发给自己的session id,而服务器要保存所有浏览器的session id 对应的session对象!如果访问服务器的客户端多了,对服务器来说是一个巨大的开销。同时也严重的限制了服务器扩展能力, 比如说我用两个机器组成了一个集群, 浏览器通过机器A登录了系统, 那浏览器中的session id对应的就是机器A上session对象, 假设浏览器的下一次请求被转发到机器B怎么办?机器B上可没有浏览器中session id对应的session对象;就会造成机器B认为这是一个全新的请求,从而让其再次登录系统(这是我们不想看到的)。

4:我们水平扩展服务器的目的,就是为了提高服务器的并发吞吐能力,让客户端不知道服务器之间的区别,让浏览器认为只有一个服务器在为自己服务。这样的话,就得想出一个在服务器之间共享session的方法:

(一)做session 的复制, 把session在两个/多个机器之间搬来搬去; 这样很显然效率低,影响服务器性能。

彻底理解cookie,session,token,就在这儿了

(二)把session集中存储到一个地方(利用缓存), 所有的机器都来访问这个地方的session, 这样就不用在多个服务器之间复制session了; 但是如果那个负责session 的机器挂了, 所有人都得重新登录一遍;所以我们也尝试把这个存储session的机器也搞出集群,增加可靠性; 但不管如何, 这小小的session 对web应用来说是一个沉重的负担。

彻底理解cookie,session,token,就在这儿了

5、抛弃session,引入Token。 

比如说, 用户F通过浏览器已经登录了系统, 服务器给他发一个令牌(token), 里边包含了用户F的 user id, 下一次用户F再次通过Http 请求访问服务器的时候, 把这个token 通过Http header 带过来,服务器拿到这个user id,就认为它已经登录了系统。但是任何人都可以伪造这个token中的user id, 所以得想点儿办法, 让别人伪造不了。

那就对数据user id做一个签名吧, 比如说用HMAC-SHA256 算法,加上一个只有服务器才知道的密钥, 对数据做一个签名, 把这个签名和数据一起作为token 返回给浏览器, 由于密钥只有服务器知道, 别人就无法伪造token了。

彻底理解cookie,session,token,就在这儿了

这个token 服务器不保存, 当浏览器把这个token 给服务器发过来的时候,服务器再用同样的HMAC-SHA256 算法和同样的密钥,对数据再计算一次签名, 和token 中的签名做个比较;如果相同, 服务器就认为在该浏览器发送请求的用户已经登录过了,并且可以直接取到用户F的user id ; 如果不相同, 数据部分肯定被人篡改过, 服务器就告诉发送者:对不起,没有认证。

彻底理解cookie,session,token,就在这儿了

这样一来, 服务器就不保存session了, 只负责生成token , 然后验证token , 用服务器的CPU计算时间获取了服务器的session 存储空间 !

解除了session这个负担, 可以说是无事一身轻;机器集群现在可以轻松地做水平扩展, 用户访问量增大, 直接加机器就行。

注意:

Token 中的数据是明文保存的(虽然我会用Base64做下编码, 但那不是加密), 还是可以被别人看到的, 所以我不能在其中保存像密码这样的敏感信息。

当然, 如果一个人的token 被别人偷走了, 那我也没办法, 我也会认为小偷就是合法用户, 这其实和一个人的session id 被别人偷走是一样的。

原文地址:https://www.cnblogs.com/hzcya1995/p/13302452.html