鉴权理论知识学习

那小白踩坑路 / 2024-08-07 / 原文

前置知识

  1. 认证
  2. 授权
  3. 鉴权
  4. 权限控制
  5. 以上四个的关系

鉴权方法

  1. HTTP基本授权认证【不安全、了解即可】
  2. Session-Cookie认证【适用中大型网站,会增加服务器费用】
  3. Token认证 【Session-Cookie的升级改良版】
  4. JWT认证   【JSON Web Token】
  5. 单点登录 【应用于多个子系统的项目,不同系统只需登录一次即可】
  6. OAuth2开发授权
  7. 联合登录和信任登录
  8. 唯一登录(一般后端处理)
  9. 扫码登录(三端配合)
  10. 一键登录(适用于APP端)

 前提概念知识

名称 概念 理解
认证 指根据声明者所特有的识别信息,确认声明者的身份。 你需要用身份证证明你自己是你自己
授权 在信息安全领域是指资源所有者委派执行者���赋予执行者指定范围的资源操作权限,以便对资源的相关操作。  银行卡(由银行派发)、门禁卡(由物业管理处派发)、钥匙(由房东派发)
鉴权 在信息安全领域是指对于一个声明者所声明的身份权利,对其所声明的真实性进行鉴别确认的过程。 门禁卡需要通过门禁卡识别器,银行卡需要通过银行卡识别器;
权限控制 将可执行的操作定义为权限列表,然后判断操作是否允许/禁止 以门禁卡的权限实现为例,一个门禁卡,拥有开公司所有的门的权限;一个门禁卡,拥有管理员角色的权限,因而可以开公司所有的门。

 认证、授权、鉴权、权限控制这四个环节前后依次发生、上下游的关系。

需要说明的是,这四个环节在有些时候会同时发生。 例如在下面的几个场景:

    • 使用门禁卡开门: 认证、授权、鉴权、权限控制四个环节一气呵成,在瞬间同时发生
    • 用户的网站登录: 用户在使用用户名和密码进行登录时,认证和授权两个环节一同完成,而鉴权和权限控制则发生在后续的请求访问中,比如在选购物品或支付时。

1、HTTP基本鉴权

在 HTTP 中,基本认证方案(Basic Access Authentication) 是允许客户端(通常指的就是网页浏览器)在请求时,通过用户提供用户名和密码的方式,实现对用户身份的验证。

因为几乎所有的线上网站都不会走该认证方案,所以该方案大家了解即可

1.1认证流程图

 1.2 认证步骤解析

1) 客户端(如浏览器): 向服务器请求一个受限的列表数据或资源,例如字段如下

 GET /list/ HTTP/1.1 

Host: www.baidu.com 

Authorization: Basic aHR0cHdhdGNoOmY=

2)服务器:客户端你好,这个资源在安全区 baidu.com 里,是受限资源,需要基本认证;

并且向客户端返回 401 状态码(Unauthorized 未被授权的)以及附带提供了一个认证域 www-Authenticate: Basic realm=”baidu.com”要求进行身份验证;

其中Basic 就是验证的模式,而 realm="baidu.com" 说明客户端需要输入这个安全域的用户名和密码,而不是其他域的

  HTTP/1.1 401 Unauthorized  
  www-Authenticate: Basic realm= "baidu.com"
3) 客户端: 服务器,我已经携带了用户名和密码给你了,你看一下;(注:如客户端是浏览器,那么此时会自动弹出一个弹窗,让用户输入用户名和密码);

输入完用户名和密码后,则客户端将用户名及密码以 Base64 加密方式发送给服务器

传送的格式如下 (其中 Basic 内容为:用户名:密码 的 ase64 形式):

GET /list/ HTTP/1.1
  Authorization: Basic Ksid2FuZzp3YW5n==
4) 服务器: 客户端你好,我已经校验了Authorization 字段你的用户名和密码,是正确的,这是你要的资源。
   HTTP/1.1 200 OK ...

优点:

简单,基本所有流行的浏览器都支持 

缺点

  1. 不安全
  • 由于是基于 HTTP 传输,所以它在网络上几乎是裸奔的,虽然它使用了 Base64 来编码,但这个编码很容易就可以解码出来。
  • 即使认证内容无法被解码为原始的用户名和密码也是不安全的,恶意用户可以再获取了认证内容后使用其不断的享服务器发起请求,这就是所谓的重放攻击。

  2. 无法主动注销:

    • 由于 HTTP 协议没有提供机制清除浏览器中的 Basic 认证信息,除非标签页或浏览器关闭、或用户清除历史记录。

使用场景:

  内部网络,或者对安全要求不是很高的网络。

2、Session-Cookie鉴权

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

什么是cookie?

众所周知,HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息);

所以为了让服务器区分不同的客户端,就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态可以通过 Cookie 去实现。

特点:

    • Cookie 存储在客户端,可随意篡改,不安全
    • 有大小限制,最大为 4kb
    • 有数量限制,一般一个浏览器对于一个网站只能存不超过 20 个 Cookie,浏览器一般只允许存放 300个 Cookie
    • Android 和 IOS 对 Cookie 支持性不好
    • Cookie 是不可跨域的,但是一级域名和二级域名是允许共享使用的(靠的是 domain)

什么是session?

Session 的抽象概念是会话,是无状态协议通信过程中,为了实现中断/继续操作,将用户和服务器之间的交互进行的一种抽象;

具体来说,是服务器生成的一种 Session 结构,可以通过多种方式保存,如内存、数据库、文件等,大型网站一般有专门的 Session 服务器集群来保存用户会话;

原理流程:

    1. 客户端: 用户向服务器首次发送请求;
    2. 服务器: 接收到数据并自动为该用户创建特定的 Session / Session ID,来标识用户并跟踪用户当前的会话过程;
    3. 客户端: 浏览器收到响应获取会话信息,并且会在下一次请求时带上 Session / Session ID;
    4. 服务器: 服务器提取后会与本地保存的 Session ID进行对比找到该特定用户的会话,进而获取会话状态;
    5. 至此客户端与服务器的通信变成有状态的通信;

特点:

    • Session 保存在服务器上;
    • 通过服务器自带的加密协议进行;

session与 Cookie 的差异:

  • 安全性: Cookie 由于保存在客户端,可随意篡改,Session 则不同存储在服务器端,无法伪造,所以 Session 的安全性更高;
  • 存取值的类型不同: Cookie 只支持字符串数据,Session 可以存任意数据类型;
  • 有效期不同: Cookie 可设置为长时间保持,Session 一般失效时间较短;
  • 存储大小不同: Cookie 保存的数据不能超过 4K;

Session-Cookie 就是把 Session 存储在了客户端的 Cookie 中

1.Session-Cookie 的认证流程图

 

2.Session-Cookie 的认证步骤解析

  1. 客户端: 向服务器发送登录信息用户名/密码来请求登录校验;

  2. 服务器: 验证登录的信息,验证通过后自动创建 Session(将 Session 保存在内存中,也可以保存在 Redis 中),然后给这个 Session 生成一个唯一的标识字符串会话身份凭证 session_id(通常称为 sid),并在响应头 Set-Cookie 中设置这个唯一标识符;

    注:可以使用签名对 sid 进行加密处理,服务端会根据对应的 secret 密钥进行解密 (非必须步骤)

  3. 客户端: 收到服务器的响应后会解析响应头,并自动将 sid 保存在本地 Cookie 中,浏览器在下次 HTTP 请求时请求头会自动附带上该域名下的 Cookie 信息;

  4. 服务器: 接收客户端请求时会去解析请求头 Cookie 中的 sid,然后根据这个 sid 去找服务端保存的该客户端的 sid,然后判断该请求是否合法;


优点:

  • Cookie 简单易用
  • Session 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理
  • 只需要后端操作即可,前端可以无感等进行操作;

缺点:

  • 依赖 Cookie,一旦用户在浏览器端禁用 Cookie,那么就 GG 思密达了;
  • 非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击);
  • Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能;
  • 对移动端的支持性不友好;

使用场景:

  • 一般中大型的网站都适用(除了 APP 移动端);
  • 由于一般的 Session 需集中存储在内存服务器上(如 Redis),这样就会增加服务器的预算,所以预算不够请谨慎选择;

前端常用的 Session 库推荐

  • 使用 express:express-session
  • 使用 koa:koa-session

 3、Token鉴权

1)、什么是Token(令牌)

Token 是一个令牌,客户端访问服务器时,验证通过后服务端会为其签发一张令牌,之后,客户端就可以携带令牌访问服务器,服务端只需要验证令牌的有效性即可。

一句话概括;访问资源接口(API)时所需要的资源凭证。

 一般Token的组成:uid (用户唯一的身份标识) + time (当前时间的时间戳) + sign (签名,Token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)

 

Token的认证流程

 

Token 认证步骤解析:

  1. 客户端: 输入用户名和密码请求登录校验;
  2. 服务器: 收到请求,去验证用户名与密码;验证成功后,服务端会签发一个 Token 并把这个 Token 发送给客户端;
  3. 客户端: 收到 Token 以后需要把它存储起来,web 端一般会放在 localStorage 或 Cookie 中,移动端原生 APP 一般存储在本地缓存中;
  4. 客户端发送请求: 向服务端请求 API 资源的时候,将 Token 通过 HTTP 请求头 Authorization 字段或者其它方式发送给服务端;
  5. 服务器: 收到请求,然后去验证客户端请求里面带着的 Token ,如果验证成功,就向客户端返回请求的数据,否则拒绝返还(401);

作者:易师傅
链接:https://juejin.cn/post/7129298214959710244
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Token 的优点:

  • 服务端无状态化、可扩展性好: Token 机制在服务端不需要存储会话(Session)信息,因为 Token 自身包含了其所标识用户的相关信息,这有利于在多个服务间共享用户状态
  • 支持 APP 移动端设备;
  • 安全性好: 有效避免 CSRF 攻击(因为不需要 Cookie)
  • 支持跨程序调用: 因为 Cookie 是不允许跨域访问的,而 Token 则不存在这个问题

Token 的缺点:

  • 配合: 需要前后端配合处理;
  • 占带宽: 正常情况下比 sid 更大,消耗更多流量,挤占更多宽带
  • 性能问题: 虽说验证 Token 时不用再去访问数据库或远程服务进行权限校验,但是需要对 Token 加解密等操作,所以会更耗性能;
  • 有效期短: 为了避免 Token 被盗用,一般 Token 的有效期会设置的较短,所以就有了 Refresh Token

2)、什么是Refresh Token(刷新Token)

业务接口用来鉴权的 Token,我们称之为 Access Token

为了安全,我们的 Access Token 有效期一般设置较短,以避免被盗用。但过短的有效期会造成 Access Token 经常过期,过期后怎么办呢?

  1. 一种办法是:刷新 Access Token,让用户重新登录获取新 Token,会很麻烦;
  2. 另外一种办法是:再来一个 Token,一个专门生成 Access Token 的 Token,我们称为 Refresh Token
    • Access Token: 用来访问业务接口,由于有效期足够短,盗用风险小,也可以使请求方式更宽松灵活;
    • Refresh Token: 用来获取 Access Token,有效期可以长一些,通过独立服务和严格的请求方式增加安全性;由于不常验证,也可以如前面的 Session 一样处理;

Refresh Token 的认证流程图:

 

 

Refresh Token 认证步骤解析:

  1. 客户端: 输入用户名和密码请求登录校验;
  2. 服务端: 收到请求,验证用户名与密码;验证成功后,服务端会签发一个 Access TokenRefresh Token 并返回给客户端;
  3. 客户端:Access TokenRefresh Token 存储在本地;
  4. 客户端发送请求: 请求数据时,携带 Access Token 传输给服务端;
  5. 服务端:
    • 验证 Access Token 有效:正常返回数据
    • 验证 Access Token 过期:拒绝请求
  6. 客户端 ( Access Token 已过期) 则重新传输 Refresh Token 给服务端;
  7. 服务端 ( Access Token 已过期) 验证 Refresh Token ,验证成功后返回新的 Access Token 给客户端;
  8. 客户端: 重新携带新的 Access Token 请求接口;

3)、Token 和 Session-Cookie 的区别

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

  • 存储地不同: Session 一般是存储在服务端;Token 是无状态的,一般由前端存储;
  • 安全性不同: Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击;
  • 支持性不同: Session-Cookie 认证需要靠浏览器的 Cookie 机制实现,如果遇到原生 NativeAPP 时这种机制就不起作用了,或是浏览器的 Cookie 存储功能被禁用,也是无法使用该认证机制实现鉴权的;而 Token 验证机制丰富了客户端类型。

4、JWT(JSON Web Token)鉴权

通过第三节,我们知道了 Token 的使用方式以及组成,我们不难发现,服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户基本信息,然后验证 Token 是否有效;

这样每次请求验证都要查询数据库,增加了查库带来的延迟等性能消耗;

那么这时候业界常用的 JWT 就应运而生了!!

什么是JWT
JWT 是 Auth0 提出的通过 对 JSON 进行加密签名来实现授权验证的方案;