许多语言在网络编程模块都会实现会话机制,即 session。利用 session,我们可以管理用户状态,比如控制会话存在时间,在会话中保存属性等。其作用方式通常如下:
也就是说,客户端只需要在登录的时候发送一次用户名密码,此后只需要在发送请求时带上 sessionId,服务器就可以验证用户是否登录了。
session 存储在内存中,在用户量较少时访问效率较高,但如果一个服务器保存了几十几百万个 session 就十分难顶了。同时由于同一用户的多次请求需要访问到同一服务器,不能简单做集群,需要通过一些策略(session sticky)来扩展,比较麻烦。
之前见过有的人把 sessionId 持久化到数据库里,只存个 id,大头还在内存里,这个操作我是看不懂的。。。
虽然 session 能够比较全面地管理用户状态,但这种方式毕竟占用了较多服务器资源,所以有人想出了一种无需在服务器端保存用户状态(称为 “无状态”)的方案,即使用 token(令牌)来做验证。
对于 token 的理解,比较常见的误区是:
简单来说,一个真正的 token 本身是携带了一些信息的,比如用户 id、过期时间等,这些信息通过签名算法防止伪造,也可以使用加密算法进一步提高安全性,但一般没有人会在 token 里存储密码,所以不加密也无所谓,反正被截获了结果都一样。(一般会用 base64 编个码,方便传输)
在 web 领域最常见的 token 解决方案是 JWT(JSON Web Token),其具体实现可以参照官方文档,这里不再赘述。
token 的安全性类似 session 方案,与明文密码的差异主要在于过期时间。其作用流程也与 session 类似:
token 的优势是无需服务器存储!!!