0


API 接口的安全性及鉴权方式

什么是 API 鉴权

公司、个人开发的系统上线后,系统中

API

暴露到互联网上会存在一定的安全风险,eg: 爬虫、恶意访问等。因此我们要先对接口调用方做一个用户鉴权,对访问 API 权限进行限制,如果鉴权通过则允许用户调用 API。根据不同的场景鉴权方案也有很多种。

常用 API 接口安全措施🔐

数据加密

数据在互联网传输过程很容易被抓包,如果直接传输,那么用户数据可能被其他人获取,导致系统安全性等问题,所以必须对数据加密。常见的做法是对关键字段加密,比如用户密码直接通过

md5

加密。

数据签名

数据在传输过程中经过加密,理论上就算被抓包,也无法对数据进行篡改,但是我们一般加密的部分其实只是在外网,现在很多服务在内网中都需要经过很多服务跳转,如果被攻入内网,则可以在任意节点篡改数据,所以这里的加数据签名可以防止内网中数据被篡改。数据签名就是由发送者产生一段无法伪造的一段数字串,来保证数据在传输过程中不被篡改。

md5算法是常用的数据签名算法,其原理是将需要提交的数据通过某种方式组合成一个字符串,然后通过md5算法生成一段加密字符串,这段加密字符串就是数据包的签名。为保证安全性,最后的密钥会在客户端和服务端各备一份。

添加时间戳

经过如上的加密,加签处理,就算拿到数据也不能看到真实的数据;但是有些攻击者不关心真实的数据,而是直接拿到抓取的数据包做恶意请求,以达到攻击的目的。我们可以使用时间戳机制,在每次请求的时候加入当前的时间,服务器端会拿到当前时间和消息中的时间相减,看看是否在一个固定的时间范围内,超过时间差的请求就视为非法请求。

限流机制

如果有用户出现频繁调用接口的情况;这种情况需要给相关用户做限流处理,常用的限流算法包括:令牌桶限流,漏桶限流,计数器限流。

  • 令牌桶限流:系统以一定速率向桶中放入令牌,填满了就丢弃令牌;请求来时会先从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务。令牌桶允许一定程度突发流量,只要有令牌就可以处理,支持一次拿多个令牌;
  • 漏桶限流:按照固定常量速率流出请求,流入请求速率任意,当请求数超过桶的容量时,新的请求等待或者拒绝服务,因此漏桶算法可以强制限制数据的传输速度;
  • 计数器限流:这是一种比较简单粗暴的算法,主要用来限制总并发数,比如数据库连接池、线程池、秒杀的并发数;计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流。

黑名单限流

如果此用户进行过很多非法操作,或者说专门有一个中黑系统,经过分析之后直接将此用户列入黑名单,所有请求直接返回错误码。

我们可以给每个用户设置一个状态比如包括:初始化状态,正常状态,中黑状态,关闭状态等等;或者我们直接通过分布式配置中心,直接保存黑名单列表,每次检查是否在列表中即可。

常用 API 鉴权方式

数据在互联网中传输是不安全的,所有处于开放环境的数据传输都可以被截取、篡改,因此数据传输必须签名加密。

签名核心解决的以下问题:

  • 请求是否合法:请求数据的是否是我规定的那部分人
  • 请求是否被篡改:请求的数据是否是原始数据,是否被篡改过
  • 防止重复请求(防重放):是否重复请求

Cookie + Session 实现 API 鉴权

Cookie + Session

是最传统的

API

鉴权方式,比如很多网站的登录模块就是靠这种方式实现用户会话管理。在服务端会生成一个

session

来保持会话状态,各个

session

是通过唯一的

session_id

来标识,以次来判断请求是那个客户端发起的,

session_id

存储在客户端的

cookie

中,后续所有的请求都会把

cookie

传到服务端,服务端解析

cookie

后找到对应的

session

进行判断。

特点:

  1. 为了使后台应用识别是那个用户发出的请求,需要在服务端存储一份用户登录信息(session),这份信息也会在相应前端请求时返回给客户端,客户端将其保存在 cookie
  2. 客户端下次请求时发送给服务端,服务端根据这个标识来识别具体时那个用户
  3. cookie 内仅包含一个 session 标识符,其他用户信息还是存储在服务端中

缺点:

  1. 性能相对较低:每一个用户经过服务端认证后服务端都要做一次记录,以方便下次请求的鉴别,通常 session 都是保存在内存中,而随着用户认证增多,服务端开销会越来越大
  2. 在一个无状态协议里注入状态,与 REST 风格不匹配
  3. 因为改方案是基于 cookie 来进行识别,cookie 如果被获取用户很容易受到 CSRF 攻击
  4. 很难跨平台,在移动端应用 sessioncookie 很难行通,你无法与移动终端共享服务端创建的 sessioncookie

API Key + API Secret

这种方式是指当请求的资源、

API Key

API Secret

匹配时,用户才可以访问对应的资源,一般还会加上时间戳等方式来进行请求的时效控制。

实现方法:

  1. 服务器生成一对 Key/Secret 保存,并下发给客户端,KeySecret 均是按照某种规则随你生成,互相无法推算
  2. 在客户端发起请求时,需要将包含 API Key 在内的所有请求参数排序(一般都是使用字典序),然后跟 API Secret(相当于加盐)一起做 hash 生成一个 sign 参数,服务器只需要按照约定的规则做一次签名计算,然后和请求的签名做比较,如果一致则验证通过,如果验证不通过则拒绝

这种模式并不是

RBAC

(角色权限控制),而是

ACL

(Access Control List: 访问控制列表) 访问控制。这种方式实现简单,占用的计算资源和网络资源都较少,安全性也可以。但是一般来说每一个 api 都需要分配一对

Key

Secret

,因此当

Key

Secret

比较多的时候,服务器会有一定的存储成本,而且服务端只能通过

API Key

来区别调用者,

API Secret

一旦泄露将造成较大的安全风险。这种模式一般适用于

Web API

有时为了避免重放攻击,会加上时间戳参数,服务单验证时如果时间超过允许范围则验证失败。

注意:加时间戳这种方式一般是在和地方系统对接中使用,一般客户端访问不要求携带时间戳,因为客户端获取的时间是用户电脑的时间,可能不准确导致无法和服务的的时间保持一致。

token 机制实现 API 鉴权

token

令牌机制是用来代替

session

的鉴权方式,

token

机制是服务端根据特定的规则生成的一串加密字符串下发给客户端,客户端请求服务端所有资源时都会携带上这个

Token

(一般设置在 header 中)。服务端来校验这个

token

的合法性,这种方式具有无状态、适合分布式、扩展性好、性能和安全性好更好等优点

image-20220116102112848

常见 Token 实现有以下几种:

  • 自定义实现 token:应用开发者根据 token 机制原理自行实现
  • JWT:即 json web token,是一种主流的 token 规范
  • Oauth:Oauth 虽然时授权规范,但其中也用到 TOken
  • HTTP Basic Authentication 认证机制
  • Web API 是基于 HTTP 协议,而 HTTP 协议本身就带有认证机制

第三方系统对接鉴权(重放攻击)

虽然上方的鉴权方式可以屏蔽大部分非法请求,可事实上,如果仿冒者监听并截取到了请求片段,然后把签名单独截取出来模仿正式请求方欺骗服务器进行重复请求,这也会造成安全问题,这攻击方式就叫重放攻击(replay 攻击)。这种方式我们就可以通过加入

timestamp + nonce

两个参数来控制请求有效性,防止重放攻击。

  • timestamp

客户端:

timestamp

由客户端生成,标识请求时间(客户端需要先检验是否和服务端时间是否一致,且双方使用统一时区计数系统)随请求一并发出,并将 timestamp 作为一个参数加入 sign 加密计算

服务端:服务端接收到请求后对比系统当前时间,设定不超过某个时间段即认为请求正常,反之则为非法请求,但这还不够,仿冒者仍然可以在这个规定的时间段内模拟请求进行重放攻击。所以更近一步可以为 sign 加上一个随机码(盐值),我们这里定义为

nonce
  • nonce

请求端:nonce 是由请求方生成的随机数(在规定时间内保证有充足的随机数产生,且重复率为0)也作为参数之一加入 sign 签名

服务端:服务器接受到请求先判定

nonce

是否被请求过(一般会放到

redis

中),如果发现

nonce

参数在规定时间是全新的则正常返回结果,反之,则判定是重放攻击。而由于以上2个参数也写入了签名当中,攻击方刻意增加或伪造

timestamp

nonce

企图逃过重放判定都会导致签名不通过而失败。

签名过程实例:

// 拼接待签名字符串
StringToSign = URL + "\n" +
        Query + "\n" +
        Content-MD5 + "\n" +
        Timestamp + "\n" +
        nonce

// 计算签名
Sign = Base64(HMAC-SHA256(ClientSecret, UTF-8-Encofing-of(stringToSign)));
  • URL: 指所访问的资源路径,如 /api/users/1
  • Query: 指请求中的 Query 参数,对参数 key 进行字典序升序排序,所有参数以 key=value 方式拼接,如 age=12&name=alex,若无此参数则设为空字符串
  • Content-MD5: body 数据的 md5sum,采用大写字符串,若无此参数则设为空字符串
  • ClientSecret:密匙
标签: http 安全

本文转载自: https://blog.csdn.net/DanielJackZ/article/details/122520971
版权归原作者 流浮生 所有, 如有侵权,请联系我们删除。

“API 接口的安全性及鉴权方式”的评论:

还没有评论