鉴权那些事
整体思路
无论什么样的服务, Web 服务总是不能绕开鉴权这个话题的, 通过有效的鉴权手段来保护网站数据, 来为特定用户提供服务.
整体来说, 有三种方式:
- Session-Cookie 鉴权
- Token 自行鉴权
- OAuth 鉴权(其实 OAuth 也是一种基于 Token 的鉴权,只是没有规定Token的生成方式)
其实在 Postman 中还显示了大量其他形式的鉴权手段, 但实际应用的要少许多, 有兴趣可自行去了解.
Session - Cookie
Session 是一种久远的技术, 它跟别的技术完全不同, Session 并不是一个独立的技术, 而是多个技术的组合封装, 一般由 Web 容器实现.
首先, Session 多见于服务端渲染项目, 比如说 JSP, 对于 JSP 项目而言, 就拥有一个 Session 对象, 开发者似乎可以自由的在 Session 中保存各种想要在前端页面中使用的信息. 比如说一些页面总是需要显示用户的昵称, ID 等, 就直接保存到 Session 中, 在 JSP 中直接取出即可.
那么 Session 作为一个对象, 显然只能在服务器中使用, 而来到浏览器时, 就已经变成了静态的 HTML 页面, 此时, Session 显然已经无法使用了, 不难想出, Session 是保存在服务器的, 那么服务器为什么每次都能够保存在服务器的这个 Session 对象呢?
这就和 Cookie 产生关系了, 服务器容器(比如说 Tomcat)会维护一个 ID-Session映射表来保存每个浏览器请求产生的Session, 然后会将这个 ID 设置成 Cookie 一并返回, 这样, 下次用户再来请求的时候就会带上该 Cookie, 服务器容器就可以从 Cookie 中取出ID, 让其访问对应的 Session.
Session 是一个非常成功的封装, 一方面它非常的易于使用, 甚至很多开发者都不知道它的存在. 但另一方面, Session 非常消耗服务器内存, 对于大型服务来说需要承担很大的压力; 另一方面则更为致命, 分布式的情况下, 内存不可被共享就意味着 Session 不能在服务器间共享, 所以分布式架构都抛弃了 Session.
JWT (JSON Web Token)
对于众多使用 Token 鉴权的方案, JWT 并没有很特殊, 最重要的一点是无状态.
既然有无状态, 那么必然存在有状态, 其实像上文 Session-Cookie 方案中, 服务器为每个用户开辟一块内存来保存一些对象, 这就可以被称为有状态的服务. 这样的话, 相信无状态也非常容易理解了, 服务器不保存每个请求的上下文即可, 每个请求对于服务器来说都是一次全新的请求, 这样是有明显的好处的.
- 服务器不必为每个用户保存其Session, 大大节约了内存, 提高了服务器的承载能力;
- 由于网络访问的随机性, 很多请求可能只访问一次就不再访问, 同时 Session 的创建和销毁都需要消耗许多资源, 这都会带来大量的性能损耗;
- 无状态使得问题变得简单, 开发者可以把精力更加集中于业务.
JWT 跟其他方案也有一些不同, 那就是 JWT 没有使用 Cookie 传输 Token, 而是每次请求的时候将 Token 保存在 header 中. Token 是怎么工作的? 生成一般是在账号, 密码验证成功后, 服务器使用账号, 用户名等字段和一段被称为盐的字符串(来源很多, 有基于日期等因素随机生成的, 有开发者提前预设的 ) 共同加密生成. 浏览器收到该 Token 后, 每次请求都需要携带该 Token, 服务端会尝试解密,如果可以成功解密, 并从中取出相应的字段, 则视为验证成功.
通常一些操作中, 还会从 Token 中的一些字段来产生一个临时的用户对象, 来帮助一些业务功能的实现.
OAuth 2.0 (Open Authorization)
授权服务, 最核心的一点, 就是存在浏览器, 服务器和授权服务器三方.
流程是, 浏览器首先将账号, 密码发往第三方的授权服务器(provider)鉴权, 授权服务器验证成功后会发放 Token, 然后浏览器再通过该 Token 访问自己真正要使用的服务.
这和机制主要用于大公司, 大公司内部产品众多, 一方面没必要开发多个用户认证体系, 另一方面, 还希望多个系统的账户体系可打通, 所以建立一个授权服务器共享账户体系是最为合适的.
另外, 其他公司引入类似于QQ登录, 微信扫码登录也是类似的机制实现的.