Vue + Spring Boot 项目实战(十四):用户认证方案与完善的访问拦截
https://learner.blog.csdn.net/article/details/102788866
知识点笔记
session
许多语言在网络编程模块都会实现会话机制,即 session。利用 session,我们可以管理用户状态,比如控制会话存在时间,在会话中保存属性等。其作用方式通常如下:
- 服务器接收到第一个请求时,生成 session 对象,并通过响应头告诉客户端在 cookie 中放入 sessionId
- 客户端之后发送请求时,会带上包含 sessionId 的 cookie
- 服务器通过 sessionId 获取 session ,进而得到当前用户的状态(是否登录)等信息
也就是说,客户端只需要在登录的时候发送一次用户名密码,此后只需要在发送请求时带上 sessionId,服务器就可以验证用户是否登录了。
session 存储在内存中,在用户量较少时访问效率较高,但如果一个服务器保存了几十几百万个 session 就十分难顶了。同时由于同一用户的多次请求需要访问到同一服务器,不能简单做集群,需要通过一些策略(session sticky)来扩展,比较麻烦。
之前见过有的人把 sessionId 持久化到数据库里,只存个 id,大头还在内存里,这个操作我是看不懂的。。。
- token
虽然 session 能够比较全面地管理用户状态,但这种方式毕竟占用了较多服务器资源,所以有人想出了一种无需在服务器端保存用户状态(称为 “无状态”)的方案,即使用 token(令牌)来做验证。
对于 token 的理解,比较常见的误区是:
- 生成方面,使用随机算法生成的字符串、设备 mac 地址甚至 sessionId 作为 token。虽然从字面意思上讲这些也算是“令牌”,但是毫无意义。这是真的 “没有状态” 了,对于状态的控制甚至需要用 session 完成,那只用 session 不好吗?
- 验证方面,把 token 存储在 session 或数据库中,比对前端传来的 token 与存储的 token 是否一致。鬼鬼,同样的骚操作。更骚的是为了提高比对效率把 token 存储在 redis 中,大家一看哇偶好高端好有道理,就直接采用这种方法了,甚至都懒得想 token 到底是个什么。。
简单来说,一个真正的 token 本身是携带了一些信息的,比如用户 id、过期时间等,这些信息通过签名算法防止伪造,也可以使用加密算法进一步提高安全性,但一般没有人会在 token 里存储密码,所以不加密也无所谓,反正被截获了结果都一样。(一般会用 base64 编个码,方便传输)
在 web 领域最常见的 token 解决方案是 JWT(JSON Web Token),其具体实现可以参照官方文档,这里不再赘述。
token 的安全性类似 session 方案,与明文密码的差异主要在于过期时间。其作用流程也与 session 类似:
- 用户使用用户名密码登录,服务器验证通过后,根据用户名(或用户 id 等),按照预先设置的算法生成 token,其中也可以封装其它信息,并将 token 返回给客户端(可以设置到客户端的 cookie 中,也可以作为 response body)
- 客户端接收到 token,并在之后发送请求时带上它(利用 cookie、作为请求头或作为参数均可)
- 服务器对 token 进行解密、验证
token 的优势是无需服务器存储!!!