HTTP 是无状态的协议,服务端无法确认访问者的身份。
身份认证的方式有:
- Authentication 认证,如基础认证等;
- Authorization 鉴权, 如:Cookie、Session、Token;
- Credentials 证书,如:证书;
1. Cookie
- HTTP 是无状态协议,每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人;
- Cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上;
- Cookie 在客户端存储,服务端不存储;
Cookie 的属性:
Cookie属性存在的问题:
- 不够安全,本地可读可写,可能被篡改;
- 不可跨域,和唯一域名进行绑定;
- 不可跨程序,如多个浏览器(现在貌似很多浏览器支持 cookie 共享了);
- Cookie 大小有限制,存储内容较少;
2. Session
- session 是另一种记录服务器和客户端会话状态的机制;
- session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中;
工作机制:
session工作机制- 用户第一次请求服务端,服务端存储 session 并生成对应的 sessionId 返回给客户端;
- 浏览器/客户端接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名;
- 用户再次请求,cookied 中带上 sessionId ,服务端通过 sessionId 查找数据库,如果存在对应的 session 则不需要进行身份认证。如果未找到则证明登录信息失效或者未登录过;
优点:
- session 存储在服务端,容量理论上无限制,可以存储很多东西;
- 存储在服务端,不容易被篡改,相对安全;
存在的问题:
- session 存储在服务端,一个过期时间内访问量过大时,会占用服务端过多资源;
- 基于 cookie 实现,无法跨域(感觉 sessionId 如果不存储在 cookie 中,那理论上也不存在跨域跨程序问题);
SessionId 为什么不能像 token 一样放在 Header 或者 Body中?
3. token
- 是客户端/浏览器访问资源接口(API)时所需要的资源凭证;
- 组成简单, token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)等;
- 客户端存储,服务端验证,访问量大时不占用资源,服务端使用解析 token 的时间来换取资源空间;
- 客户端存储不一定需要绑定在 cookie 中,请求时只需要在 Header 或者 Body 中带上即可,不存在跨域问题;
token 的鉴权流程:
token 鉴权流程
4. refreshToken
登录成功之后生成一个 refreshToken,同时生成一个 Token ,两个 token 都回传到客户端,客户端对这两个 Token 都进行保存,其关系如下:
refreshToken和Token几个特点:
- 一对多,可以根据 refreshToken 生成多个 token;
- 一般业务下,任意时刻只有一个 refreshToken 和一个 token 有效;
- 不一定是单纯的 Map 中的 Key-Value 关系,更有可能是通过算法建立的关联;
- token 是根据 refreshToken 生成的;
token 和 refreshToken 中包含了很多信息,最重要的几个是:用户信息、有效期。
客户端有两种类型的接口:功能性接口 + refresh 接口;
功能性接口就是业务接口,需要身份验证时直接使用 token 作为令牌来调用。后台解析 token 获取到用户信息、有效期等;
refresh 接口就是使用 refreshToken 去生成新的 token 的接口;
refreshToken 是长时间不变的,一旦发生改变则表示登录状态失效,旧的 refreshToken 不能用来生成 token了,refreshToken 和 token 的关联关系也就失效了。
对于 token,采用 “客户端主动刷新 token ”+ “服务端设置并检测 token 有效性” 的方式来保证 token 的刷新频率,以此来防止 token 被破解,进而保证接口调用的安全性。
总结:
- 客户端可以将 refreshToken 作为入参,主动调用 refresh 接口来更新 token 并存储到本地;
- 客户端使用 token 调用功能性接口时,服务端解析 token 中的有效期,如果失效则告诉客户端,客户端去调用 refresh 接口刷新 refreshToken;
一般 token 失效之后客户端的处理方式有两种,第一种是发送通知触发 refresh 方法。但是更好的方案是客户端调用 refresh 接口后,获取到 token 的有效期并保存,然后在有效期内固定频率地去调用 refresh 接口刷新 token 并更新,这样可以最大限度避免 token 失效的情况;
5. 总结
- cookie 主要问题在于跨域或者跨程序,且客户端的 cookie 容易被篡改;
- session 的主要问题是存储在服务端,占用过多资源,跨程序问题倒是可以通过其他手段解决;
- token 完美解决跨程序和存储问题,服务端使用解析时间换取存储空间,但是如果失效时间过短,失效之后需要重新登录的问题;
- refreshToken 通过 Key-Value 的方式和当前唯一有效的 token 建立印射。refreshToken 负责登录,失效时间很长,更新频率很低,解决了频繁登录的问题。Token 负责接口调用,失效时间短,更新频率快,解决了安全问题;
网友评论