Cookie
直接在Cookie中存信息可谓是上古时代的操作了,在服务器还没有那么便宜的情况下,好多网站选择将用户的登录信息存在cookie中,他们把用户名或者用户id转换并签名之后,直接存入Cookie,如果有其他需要的信息,也是如此操作
转换或签名可以是加盐md5,也可以是使用secret的双向加密
用户第二次访问网站的时候,代码中对这段信息进行验证,看看是否是正确的签名的
这样做的好处是: 不会再占用服务器资源,直接就在cookie中读取数据,获得结果
坏处是: 登录凭据容易被窃取,尤其是那个年代还没有流行https,如果被中间人了,或者以另一种方式拿到了cookie,那就会被窃取登录,另外,每个数据还可能是分开存储的,因此容易被篡改
当然那时的互联网也并没有那么发达,cookie也就存存用户名什么的用于显示
Session
后来网速变快了,web 应用高速发展,大家意识到了很多问题,cookie 大小不够啊,cookie 每个 key 都这么搞一下暴露太多了等等
从原理上来说,Session 就是 Cookie
客户端进入网站后,服务器分配一个 Session ID 给客户端种入 Cookie,用户登录时,在服务器查询 Session ID,在服务器写入 Session Object,这个对象里存了用户的登录数据,比如 id 啦,用户名啦,登录状态 / 角色等等
另外分配 Session ID 也可以是懒分配,也就是等到在服务器存 Session Object 的时候再分配也没有关系,Session ID 的分配可以是用 UserID 来进行加密分配,也可以用毫不相关的时间等信息进行加密分配,只需要保证这个 sid 唯一,不容易被伪造即可
Session 的存放也是可重可轻,如果觉得 Session 很重要,那么可以放入 mysql,如果觉得 Session 不怎么重要,甚至可以放入内存,重启丢失
Session 到至今还是非常非常多的网站在用,原因就是在于其实除了 https 以外的问题,并没有什么问题,IE >= 10 之后,Cookie 也可以跨域,那么 Session 就没有什么问题
好处是: 在客户端除了 sid 以外,看不到任何信息,当然不太容易篡改
坏处是: 取 Session 的时候,是会需要再 query 一次的 也容易被窃取,当然这并不是 Session / Cookie 的锅,http 下,啥都是一清二楚的
另外,优缺点都是相对于时代来说的,存 Cookie 的时代服务器的性能不高,也没有 memcache 或者 redis 这种东西,存入 mysql 就需要再 query 一次,负载均衡当然不能同步 内存中的 Session,Cookie 成为了首选,那么现在呢,这点算力恐怕算不了什么,那么 Session 的那个坏处,就应该被划掉,Session 理所当然成为了流行的会话管理方式
Session 和 Cookie 都不需要前端介入,服务端通过 Set-Cookie http 头就可以完成 sid 和 Cookie 的更新
Token Based
上边两种方法代表了两种存登录凭据的思想,一种是把凭据存客户端,一种是把凭据存服务端
那么随着前后端分离的运动,上边两种的登录凭据的思想也发展出了两种不使用 Cookie 的方法
把凭据存服务端的 Session,把他的Token,单拿出来,在JSON中传递,或者在 http 头里传递或者其他方式传递
JWT(JSON Web Token) 代表了把凭据存客户端的思想,和当时的 Cookie 有点像,登录的时候把那些需要的信息 base64 编码作为一段,然后再对这些字段用 secret 进行签名,连起来这么一段 Token 去发给客户端作为凭据
凭据存在客户端的好处是: 因为登录状态都是跟着客户端跑的,时效信息都存在客户端,Session 如果过期了,要对 Session 数据库进行垃圾清理,那么凭据存在客户端就不需要,而且因为都是跟着客户端跑的,在服务器扩大搞集群,搞异地多活,就不需要考虑读数据库这种事情,因为都是客户端请求为 based ,随便哪个服务器来 handle 请求都没有问题
凭据存客户端坏处是: 当凭据内容越来越多,Token 也会越来越长,每一次请求都会携带这么大这么长的内容,显然不是非常合适
JWT 还有个问题就是中间那部分是 base64 编码的,如果熟悉标准的话,等于就是明文存储凭据了,虽然不能改,当然还是能看到
Token 类的鉴权需要前端参与并存储,存储一般会放在 localStorage等地方,因此其实是比较容易受到 XSS 的影响 Cookie 类的鉴权容易受到 CSRF 的影响
总结
其实只言片语还是没法概括到所有的情况,只能大体的对Token 或者 Cookie 以及 凭据存服务端或者客户端的优缺点进行想象,究竟去使用哪一种鉴权方式,还是应该基于业务,对业务有非常深入的理解,以及稍带一些长远的思考