Web技术发展初期,因为http协议无状态的特性,Web业务系统无法获知Client端到底做了哪些操作、谁做的操作、在什么情况下作的操作。为了解决上述业务系统遇到的难题、优化用户使用体验,cookie技术应运而生。其特点如下:
产生方式 | 存储位置 | 传输方式 | 典型应用 | 安全性 | http传输效率 | 业务系统集成的难度 |
Client自行维护 | Client | http的头部字段:cookie | 记住密码自动登录 | 因为所有信息保存在客户端,安全性较低 | 随着业务复杂度的提升cookie内容极度膨胀,从而降低了http通信的效率(互联网初期所有的用户状态信息都是通过cookie传输的) | 低 |
因为Cookie的安全性差,且随着用户业务复杂度的提升导致cookie内容极度膨胀从而降低了http通信的效率。另外,Web应用产生的诸如购物等的数据一般都会存储在服务端系统中,按理来说也没必要全部通过cookie反复传递。于是,session这种存储于服务器本地的鉴权方案得以广泛使用,其特点如下:
产生方式 | 存储位置 | 传输方式 | 典型应用 | 安全性 | http传输效率 | 业务系统集成的难度 |
Server产生和维护 | Server |
Client首次访问Server输入账户信息认证成功后,Server会产生相关session及session-id。然后: 1)Server通过http的set-cookie头部告知Client后续请求通过该session-id识别身份和状态 2)Client通过http的cookie头部传递session-id到Server 3)Server收到请求后提取到session-id后查询session存储位置以确定身份 |
身份鉴权 | 因为信息保存在服务端,安全性相对cookie较高 | cookie字段总是传递session-id,内容一般不会变化,对http的传输效率几乎没有影响 |
高: 1)高并发业务系统意味着Server需要读写大量的session,给Server增加了很大的压力 2)生产系统一般都是集群部署且前置负载均衡,如果一个用户的多次访问被调度到不同服务器节点则session功能失效 3)为了解决问题2,需要实现session复制的功能,难度较大且浪费Server存储资源 4)为了解决问题3,现在一般都将session存储在Redis,不论负载均衡调度到哪个节点都需要到Redis服务器查询一遍再返回,一定程度上增加了http访问的耗时 5)因为Redis的高速查询都是在内存中进行,为了避免session这么重要的数据出现单点故障,一般也都需要Redis服务器集群部署,技术难度大成本高 |
随着互联网的发展,移动终端逐渐占领了用户消费的绝对领地。但是原始的android系统对于cookie的支持存在诸多问题,而当时的鉴权方案不论是cookie还是session其实都依赖于cookie,于是亟待一种全新的方案解决移动终端的鉴权难题。
同时,因为session在使用上的复杂度较高,业界一直在想:“有没有一种能够不需要Server记录且实时维护信息却能够鉴权的方案呢?”(Tips:当然,token也并未能在全部场景下解决session存在的不足,只是满足了较大部分的业务场景)。
天工凑巧,出现了token,其特点如下:
产生方式 | 存储位置 | 传输方式 | 典型应用 | 安全性 | http传输效率 | 业务系统集成的难度 |
Server产生 |
服务端: 1)生成Token存在数据库 2)生成Token存在Redis
客户端: JWT机制 |
A)如果存储在服务端: 工作方式跟Session一致
B)如果存储在客户端: Client首次访问Server输入账户信息认证成功后,Server会产生token。然后: 1)Server通过http的头部告知Client后续请求通过该token识别身份和状态 2)Client通过http的头部传递token到Server 3)Server收到请求后提取到token后使用密钥解密token以确定身份 |
APP、小程序 | 因为信息保存在服务端,安全性相对cookie较高 | 头部传递的内容一般变化不大,对http的传输效率几乎没有影响 |
A)如果存储在服务端,难度跟session一致,高(详见session的分析):
B)如果存储在客户端,则一般是使用JWT生成且只需要Server使用密钥解密即可,难度:低 //(Tips:JWT这种方式最大的不足就是一旦给Client发布了token就对其完全失去了控制,不适用的典型场景就是:难以主动封禁个别恶意用户) |
细节请参考: https://www.zhihu.com/question/19786827/answer/2064471064