API网关的权限验证实践

  1. 概述
公司、个人开发的系统上线后,系统中 API 暴露到网络上会存在一定的安全风险,比如:爬虫、恶意访问、错误访问等 。API没有安全性,用户可以任意注册即可无限次访问和调用API,且没有请求与特定用户数据关联的简单方法,就无法防止恶意用户的恶意请求等 。
常用 API 接口安全措施如下几种:
(1)数据加密
数据在互联网传输过程很容易被抓包,如果直接传输,那么用户数据可能被其他人获取,导致系统安全性等问题,所以必须对数据加密 。常见的做法是对关键字段加密,比如用户密码直接通过 md5 加密 。
(2)数据签名
数据在传输过程中经过加密,理论上就算被抓包,也无法对数据进行篡改,但是我们一般加密的部分其实只是在外网,现在很多服务在内网中都需要经过很多服务跳转,如果被攻入内网,则可以在任意节点篡改数据,所以这里的加数据签名可以防止内网中数据被篡改 。数据签名就是由发送者产生一段无法伪造的一段数字串,来保证数据在传输过程中不被篡改 。md5算法是常用的数据签名算法,其原理是将需要提交的数据通过某种方式组合成一个字符串,然后通过md5算法生成一段加密字符串,这段加密字符串就是数据包的签名 。为保证安全性,最后的密钥会在客户端和服务端各备一份 。
(3)添加时间戳
经过如上的加密,加签处理,就算拿到数据也不能看到真实的数据;但是有些攻击者不关心真实的数据,而是直接拿到抓取的数据包做恶意请求,以达到攻击的目的 。我们可以使用时间戳机制,在每次请求的时候加入当前的时间,服务器端会拿到当前时间和消息中的时间相减,看看是否在一个固定的时间范围内,超过时间差的请求就视为非法请求 。
(4)限流机制
如果有用户出现频繁调用接口的情况;这种情况需要给相关用户做限流处理,常用的限流算法包括:令牌桶限流,漏桶限流,计数器限流 。令牌桶限流:系统以一定速率向桶中放入令牌,填满了就丢弃令牌;请求来时会先从桶中取出令牌,如果能取到令牌,则可以继续完成请求,否则等待或者拒绝服务 。令牌桶允许一定程度突发流量,只要有令牌就可以处理,支持一次拿多个令牌 。漏桶限流:按照固定常量速率流出请求,流入请求速率任意,当请求数超过桶的容量时,新的请求等待或者拒绝服务,因此漏桶算法可以强制限制数据的传输速度 。计数器限流:这是一种比较简单粗暴的算法,主要用来限制总并发数,比如数据库连接池、线程池、秒杀的并发数;计数器限流只要一定时间内的总请求数超过设定的阀值则进行限流 。
(5)黑名单限流
如果此用户进行过很多非法操作,或者说专门有一个中黑系统,经过分析之后直接将此用户列入黑名单,所有请求直接返回错误码 。我们可以给每个用户设置一个状态比如包括:初始化状态,正常状态,中黑状态,关闭状态等等;或者我们直接通过分布式配置中心,直接保存黑名单列表,每次检查是否在列表中即可 。
常用的安全防范有以下方式:API Keys、Basic Auth、Hmac、OAuth 。本文主要讨论基于OAuth协议的API安全验证 。本文主要介绍基于OAuth协议(Client Credentials)的实践 。
  1. 系统架构
下图是一个笔者亲身经历的一个例子,到目前为止,运转良好 。API服务服务网关采用基于Kong API网关的实现,认证中心是实现OAuth 2.0协议的权限认证系统,服务提供系统设置基于IP的白名单访问 。
OAuth 2.0是一种用户验证和授权用户的流行方法,此方法依赖于身份验证服务器和API服务器进行通信以授予访问权限,在笔者的前面的文章中已经详细阐述OAuth的原理,在这里就不在赘述,想看的读者可以翻看历史记录找到该篇文章 。下图标注了详细的流程 。
API网关的权限验证实践

文章插图
 
  1. JWT令牌的理论
JWT(全称:Json Web Token)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息 。该信息可以被验证和信任,因为它是数字签名的 。如有读者想了解详细的JWT规范,可以访问RFC7519的官方网站:https://datatracker.ietf.org/doc/html/rfc7519 。
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature) 。在传输的时候,会将JWT的3部分分别进行Base64编码后用 。进行连接形成最终传输的字符串 。JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret) 。


推荐阅读