用户身份认证
用户名密码认证
我们最常见的用户身份认证模式就是账号、密码方式,登录一个网站,引导你到用户登录界面,输入用户名、密码、验证码,然后验证通过后跳转到你要访问的页面去。
二维码认证
当然现在还有比较流行的扫码模式,弹出一个二维码,你用 APP(必须已登录,否则无法匹配扫码用户的身份)扫描这个二维码,然后在 APP 端同意登录,这样网页端就会得到允许登录的通知,同时也能获取到是哪个用户登录。
OAuth 认证
使用第三方用户体系时会使用这种模式来认证,简单的描述就是由第三方服务器完成用户身份的认证、授权,告诉用户需要访问的网站你用我认证通过的标志(token)来确定用户身份就好了。大家达成一致协议,后续就跟普通玩法一样了。今天我们重点介绍的就是这种模式。
无论哪种身份认证方式,只要用户通过了认证,这之后的访问过程中,只要我们没有主动登出,用户身份也没有过期,SSO(单点登录)也没有踢出你的身份,那始终是可以正常访问资源的。在普通用户使用层面上是无感知的,他知道当前用的身份就是我自己,那么对于服务器是怎么判断当前访问资源的用户是谁呢?
服务端判断身份
cookie、session
服务端在用户认证通过后,在 response 的 cookie 中加一个 JSESSIONID(随机标识)返回给前端,同时在服务端 session 中存储这个 id 对应的用户对象,这样在之后的请求中我们都能通过前端传来的 JSESSIONID 找到 session 中对应的用户数据,也就能知道是哪个用户访问资源了。
当然了,你要是头铁,完全也可以把用户对象序列化后放在 cookie 中回传给前端,后端在每次请求中解析这个 cookie,拿到用户数据,但估计你离被辞退也不远了。
由于 session 默认都是在本机存储的,这对于集群服务就麻烦了,获取不到对应的用户对象,后来就演变出在数据库、redis 等缓存中间件中存储 session 数据。数据库存 session 性能比较差,现在基本都是缓存中间件来存储。
token(OAuth2.0)
一个字符串,比如 cdf62cb2-b6de-460c-8856-d9339d923012,可以根据它通过指定的查询方式,获取用户信息。比如如果配置了通过 redis 获取,则这个 token 就是 key,获取的 value 就是用户信息。
其实这种方式跟 cookie 非常像,为什么又单独搞出一个 OAuth2.0 模式呢?因为 cookie 不能跨终端,某些用户设置浏览器不允许访问 cookie 也会失效。而 token 就不一样了,只是一个字符串,完全可以跨终端,而且保存在 js 中也不需要 cookie 支持。
JWT(JSON Web Tokens)
与 token 模式相同,只不过这里存储的不是 token 那么简单的字符串,而是一个包含有效数据的加密字符串,比如:BearereyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJhZG1pbiIsImNyZWF0ZWQiOjE1Nzg4OTgxNzIzNjQsImV4cCI6MTU3OTUwMjk3Mn0._PxIFHqBBx1RN1C3plyT8_9TepCs35lSU2P9n1jZ1Esvmi5yK2t6h4pl_QsRIBjFOam2TFxwln68lF2BEAcu5Q,正确解密后可以直接拿到用户信息,比如用户 id、用户名等等,就看你敢往里面塞多少内容了。好处是不需要再次去别的地方查用户数据,坏处么,塞得东西越多,每次传输的内容就越大,而且是存储在客户端的,敏感信息不应该放在里面。
JWT 的构成
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature)。第三部分是一个签证信息,这个签证信息由三部分组成:
- header (base64 后的)
- payload (base64 后的)
- secret
OAuth2.0 介绍
OAuth2.0 的简单交互流程如下图:
这里简化了用户授权过程中后端的交互,因为 OAuth2.0 的授权模式有四种:
- 密码模式(resource owner password credentials)这种模式是最不推荐的,因为客户端会知道用户密码支持 refresh token
- 授权码模式(authorization code)这种模式算是正宗的 oauth2 的授权模式设计了 auth code,通过这个 code 再获取 token支持 refresh token
- 简化模式(implicit)如图这种模式比授权码模式少了 code 环节,回调 url 直接携带 token不支持 refresh token
- 客户端模式(client credentials)这种模式直接根据 client 的 id 和密钥即可获取 token,无需用户参与这种模式比较合适消费 api 的后端服务,比如拉取一组用户信息等不支持 refresh token
本文暂时没有评论,来添加一个吧(●'◡'●)