前端鉴权方案

Daotin 于 2022-07-09 发布 编辑

鉴权也叫身份验证(Authentication),是指验证用户是否拥有访问系统的权利。

Session-Cookie  认证是利用服务端的 Session(会话)和浏览器(客户端)的 Cookie 来实现的前后端通信认证模式。

由于 HTTP 请求时是无状态的,服务端正常情况下无法得知请求发送者的身份,这个时候我们如果要记录状态,就需要在服务端创建 Session 会话,将相同客户端的请求都维护在各自的会话记录中,每当请求到达服务端时,先校验请求中的用户标识是否存在于 Session 中,如果有则表示已经认证成功,否则表示认证失败。

Cookie 主要用于以下三个方面:

下图为 Session-Cookie 认证的工作流程图:

5

  1. 服务端在接收到来自客户端的首次访问时,会自动创建 Session(将 Session 保存在内存中,也可以保存在 Redis 中),然后给这个 Session 生成一个唯一的标识字符串会话身份凭证  session_id(通常称为  sid),并在响应头  Set-Cookie  中设置这个唯一标识符。
  2. 浏览器收到请求响应后会解析响应头,并自动将  sid  保存在本地 Cookie 中,浏览器在下次 HTTP 请求时请求头会自动附带上该域名下的 Cookie 信息
  3. 服务端在接收客户端请求时会去解析请求头 Cookie 中的  sid,然后根据这个  sid  去找服务端保存的该客户端的  sid,然后判断该请求是否合法
  4. 一旦用户登出,服务端和浏览器将会同时销毁各自保存的会话 ID,服务端会根据数据库验证会话身份凭证,如果验证通过,则继续处理

优点:

  1. Cookie 简单易用,在不受用户干预或过期处理的情况下,Cookie 通常是客户端上持续时间最长的数据保留形式
  2. Session 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理

缺点:

  1. 非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)
  2. Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能
  3. 用户认证后,服务端做认证记录,如果认证的记录被保存在内存中,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权资源,这样在分布式的应用上,相应的限制了负载均衡的能力,也意味着限制了应用的扩展能力

Token 认证

Token 和 Session-Cookie 认证方式中的 Session ID 不同,并非只是一个标识符。Token 一般会包含  用户的相关信息,通过验证 Token 不仅可以完成身份校验,还可以获取预设的信息。

6

基于 Token 的身份验证方法:

  1. 用户输入登录信息并请求登录
  2. 服务端收到请求,验证用户输入的登录信息
  3. 验证成功后,服务端会  签发一个 Token(通常包含用户基础信息、权限范围和有效时间等),并把这个 Token 返回给客户端
  4. 客户端收到 Token 后需要把它存储起来,一般会放在 localStorage 里(一般不放 Cookie 因为可能会有跨域问题,以及安全性问题)
  5. 后续客户端每次向服务端请求资源的时候,将 Token 附带于 HTTP 请求头 Authorization 字段中发送请求
  6. 服务端收到请求后,去校验客户端请求中 Token,如果验证成功,就向客户端返回请求的数据,否则拒绝返还

优点:

缺点:

Token 生成方式

最常见的 Token 生成方式是使用 JWTJson Web Token),它是一种简洁的、自包含的方法,用于通信双方之间以 JSON 对象的形式安全的传递信息。

使用 Token 后,服务器端并不会存储 Token,那怎么判断客户端发过来的 Token 是合法有效的呢?

答案其实就在 Token 字符串中,其实 Token 并不是一串杂乱无章的字符串,而是通过多种算法拼接组合而成的字符串。

JWT 算法主要分为 3 个部分:header(头信息),playload(消息体),signature(签名)。

关于 JWT,这里简单说明一下,具体细节大家可以去看一下 JWT 官网

或者参考阮一峰的这篇文章:JSON Web Token 入门教程

Session-Cookie 认证和 Token 认证有很多类似的地方,但是 Token 认证更像是 Session-Cookie 认证的升级改良版。

1、使用 Token,服务端不需要保存状态. 在 session 中 sessionid 是一个唯一标识的字符串,服务端是根据这个字符串,来查询在服务器端保持的 session,这里面才保存着用户的登陆状态。但是 token 本身就是一种登陆成功凭证,他是在登陆成功后根据某种规则生成的一种信息凭证,他里面本身就保存着用户的登陆状态。服务器端只需要根据定义的规则校验这个 token 是否合法就行。

2、Token 验证机制丰富了客户端类型。session-cookie 是需要 cookie 配合的,那么在 http 代理客户端的选择上就只有浏览器了,因为只有浏览器才会去解析请求响应头里面的 cookie,然后每次请求再默认带上该域名下的 cookie。但是我们知道 http 代理客户端不只有浏览器,还有原生 APP 等等,这个时候 cookie 是不起作用的,或者浏览器端是可以禁止 cookie 的,但是 token 就不一样,他是登陆请求在登陆成功后再请求响应体中返回的信息,客户端在收到响应的时候,可以把他存在本地的 cookie,storage,或者内存中,然后再下一次请求的请求头重带上这个 token 就行了。简单点来说 cookie-session 机制他限制了客户端的类型,而 token 验证机制丰富了客户端类型。

3、时效性。session-cookie 的 sessionid 实在登陆的时候生成的而且在登出事时一直不变的,在一定程度上安全就会低,而 token 是可以在一段时间内动态改变的。

4、可扩展性。token 验证本身是比较灵活的,一是 token 的解决方案有许多,常用的是 JWT,二来我们可以基于 token 验证机制,专门做一个鉴权服务,用它向多个服务的请求进行统一鉴权。