前端鉴权背景
原因:http请求无状态
鉴权方式
1. 初窥:前端全局变量、sessionStorage、localStorage
a. 利弊
- 全局变量不利于持久化, 一刷新页面就没有
- sessionStorage、localStorage虽可以持久化,但操作麻烦,要前端存、前端手动带上给服务端
2. 基础:前端存储cookie
a. 介绍
相比sessionStorage、localStorage等本方式,借助 HTTP 头、浏览器能力,cookie 可以做到前端无感知
b. 原理
- 在提供标记的接口,通过 HTTP 返回头的 Set-Cookie 字段,直接「种」到浏览器上
- 浏览器发起请求时,会自动把 cookie 通过 HTTP 请求头的 Cookie 字段,带给接口
2. 方案一:服务端session
a. 介绍
- 浏览器登录发送账号密码,服务端查用户库,校验用户
- 服务端把用户登录状态存为 Session,生成一个 sessionId
- 通过登录接口返回,把 sessionId set 到 cookie 上
- 此后浏览器再请求业务接口,sessionId 随 cookie 带上
- 服务端查 sessionId 校验 session
- 成功后正常做业务处理,返回结果
b.服务端存储
- redis: 内存型数据库,性能好
- mysql: 性能不高
- 应用内存: 重启就没了
c.问题
- 服务端存放session
- 分布式存储session
3. 方案二:token
a. 介绍
- 用户登录,服务端校验账号密码,获得用户信息
- 把用户信息、token 配置编码成 token,通过 cookie set 到浏览器
- 此后用户请求业务接口,通过 cookie 携带 token
- 接口校验 token 有效性,进行正常业务接口处理
b. 步骤
- 存储方式: 前端cookie
- 存储内部: 被编码过的有效期、使用现在、用户信息
c. 编码
- base64
- 签名防篡改
d. 问题
- 新增cookie数量
- cookie格式没有规范
4. 方案三:jwt
a. 介绍和格式
jwt(json web token)是一个开放标准,定义了一种传递 JSON 信息的方式。这些信息通过数字签名确保可信。
b. 原理
- access token:用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活
- refresh token :用来获取 access token,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的 session 一样处理
c. session和token的区别
- session:我们通常认为 session 是「种在 cookie 上、数据存在服务端」的认证方案
- token: token 是「客户端存哪都行、数据存在 token 里」的认证方案
5. sso (单点登录)
a. 介绍
一次登录,全线通用」的能力,叫做「单点登录」
b. “假的”单点登录
如果业务系统都在同一主域名下,比如wenku.baidu.com、tieba.baidu.com,就好办了。可以直接把 cookie domain 设置为主域名 baidu.com,百度也就是这么干的
c. “真实”单点登录
a.com、b.com、c.com一次登录, 全系统可用
- 用户进入 A 系统,没有登录凭证(ticket),A 系统给他跳到 SSO
- SSO 没登录过,也就没有 sso 系统下没有凭证(注意这个和前面 A ticket 是两回事),输入账号密码登录
- SSO 账号密码验证成功,通过接口返回做两件事:一是种下 sso 系统下凭证(记录用户在 SSO 登录状态);二是下发一个 ticket
- 客户端拿到 ticket,保存起来,带着请求系统 A 接口
- 系统 A 校验 ticket,成功后正常处理业务请求
- 此时用户第一次进入系统 B,没有登录凭证(ticket),B 系统给他跳到 SSO
- SSO 登录过,系统下有凭证,不用再次登录,只需要下发 ticket
- 客户端拿到 ticket,保存起来,带着请求系统 B 接口
d. 完整版sso
- 在 SSO 域下,SSO 不是通过接口把 ticket 直接返回,而是通过一个带 code 的 URL 重定向到系统 A 的接口上,这个接口通常在 A 向 SSO 注册时约定
- 浏览器被重定向到 A 域下,带着 code 访问了 A 的 callback 接口,callback 接口通过 code 换取 ticket
- 这个 code 不同于 ticket,code 是一次性的,暴露在 URL 中,只为了传一下换 ticket,换完就失效
- callback 接口拿到 ticket 后,在自己的域下 set cookie 成功
- 在后续请求中,只需要把 cookie 中的 ticket 解析出来,去 SSO 验证就好
- 访问 B 系统也是一样