对外API接口的安全性设计及鉴权方式

一个公司需要拓展业务时,内部的业务系统往往需要跟外部系统交互,比如现在用户希望在支付宝或微信上交电费,话费,转账…那么电力公司、运营商、银行就需要跟支付宝和微信打通内部系统与支付宝微信系统之间的网络,提供相关api接口。

像这种对外的api接口往往对安全性有严格要求,本文整理了一下常用的api鉴权方式以及安全措施(如有不当之处,请路过的大佬指正)。

API鉴权方式

直接把API暴露到互联网上给外部系统是存在安全风险的,因此我们要先对接口调用方做一个用户鉴权,对API权限划分,如果鉴权通过则允许用户调用API。根据不同的场景,鉴权方案也有很多种。

API Key + API Secret实现API鉴权

这种方式是指当请求的资源、API Key 和 API Secret匹配时,用户才可以访问对应的资源,一般还会以时间戳等方式来进行请求的时效控制。

其原理为:

  1. 服务器给每个客户端生成一对Key/Secret保存,并告知客户端,Key和Secret之间没有任何关系,相互之间不能推算;
  2. 发起请求时,会把包括API Key在内的所有的请求参数排序,然后跟API Secret一起做hash生成一个sign参数,服务器只需要按照约定的规则做一次签名计算,然后和请求的签名作比较,如果一致,则验证通过。

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

需要注意的是,这种模式并不是RBAC,而是ACL访问权限控制。这种方式实现简单,占用的计算资源和网络资源都较少,安全性也可以。但是一般来说每一个api用户都需要分配一对Key和Secret,因此当Key和Secret比较多的时候,服务器会有一定的存储成本 ,而服务端只能通过API Key来区别调用者,API Secret一旦泄密,将造成很大的安全风险。

这种模式适用于大多是的Web API,除非需要在token中承载更多信息或者用户多到影响服务器部署。

Cookie + Session实现API鉴权

Cookie + Session是最传统的API鉴权方式,比如很多网站的登录模块就是靠这种方式实现会话管理。

在服务端会生成一个session来保存会话状态,各个session是通过唯一的session_id来标识的,一次判断请求是哪个客户端发起,session_id存储在客户端的cookie中。

后续的所有请求都会把cookie传到服务器端,服务器端解析cookie后找到对应的session进行判断。
在这里插入图片描述
因此这种鉴权方式具有以下特点:

  1. 为了使后台应用能识别是哪个用户发出的请求,需要在后台服务器存储一份用户登录信息(即session),这份信息也会在响应前端请求时返回给前端,前端将其保存在cookie;
  2. 下次请求时前端发送给后端应用,后端应用就可以识别这个请求是来自哪个用户;
  3. cookie内仅包含一个session标识符而诸如用户信息、授权列表等都保存在服务端的session中。

其优点是:

  1. 比较传统,对开发来说资料较多,语言支持完善;
  2. 较易于扩展,外部session存储方案已经非常成熟了(比如Redis)。

但也有如下缺点:

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

总的来说,如果是传统的web网站,且同时认证的人数不是足够大(比如只是内部使用)的都可以用这种方式,很多网站依旧采用该方式。

token机制实现API鉴权

token令牌的机制是用来代替session的鉴权方式,现在很多api的鉴权都是通过token。

在这里插入图片描述
token机制是服务器端生成的一串加密串发放给客户端,客户端请求服务器端所有资源时会带上这个Token,由服务器端来校验这个token的合法性。其具有无状态、适合分布式、扩展性好、性能高和安全性好等优点。
在这里插入图片描述
常见的token实现有以下几种:

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

API接口的安全措施

以上是博主总结的一些API鉴权方式。但是在调用API的过程中还需要保证数据在传输过程中的安全性、判断数据是否到达服务器以及服务器如何识别传到服务器的数据是否正确,如何不被攻击。

数据加密

数据在传输过程中是很容易被抓包的,如果直接传输,比如通过http协议,那么用户传输的数据可以被任何人获取,所以必须对数据加密。

常见的做法对关键字段加密比如用户密码直接通过md5加密;现在主流的做法是使用https协议,在http和tcp之间添加一层加密层(SSL层),这一层负责数据的加密和解密。

现在主流的加密方式有对称加密和非对称加密。

  • 对称加密:对称密钥在加密和解密的过程中使用的密钥是相同的,常见的对称加密算法有DES,AES,计算速度快,但是在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥,如果一方的秘钥被泄露,那么也容易泄密;
  • 非对称加密:服务端会生成一对密钥,私钥存放在服务器端,公钥可以发布给任何人使用,优点就是比起对称加密更加安全,但是加解密的速度比对称加密慢太多了,广泛使用的是RSA算法。

以上两种方式各有优缺点,而https的实现方式正好是结合了两种加密方式,整合了双方的优点,在安全和性能方面都比较好。

数据签名

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

数据签名就是由发送者产生一段无法伪造的一段数字串,来保证数据在传输过程中不被篡改。

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

添加时间戳

经过如上的加密,加签处理,就算拿到数据也不能看到真实的数据;但是有些攻击者不关心真实的数据,而是直接拿到抓取的数据包做恶意请求,以达到攻击的目的。

我们可以使用时间戳机制,在每次请求的时候加入当前的时间,服务器端会拿到当前时间和消息中的时间相减,看看是否在一个固定的时间范围内,超过时间差的请求就视为非法请求。

限流机制

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

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

黑名单机制

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

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

数据合法性校验

这应该是每个系统都会有的处理机制,只有在数据是合法的情况下才会进行数据处理;每个系统都有自己的验证规则,当然也可能有一些常规性的规则,比如身份证长度和组成,电话号码长度和组成等等。合法性校验包括:常规性校验以及业务校验。

  • 常规性校验:包括签名校验,必填校验,长度校验,类型校验,格式校验等;
  • 业务校验:根据实际业务而定,比如账户余额不能小于0等.

总结

本文大致列举了几种常见的API鉴权机制和安全措施,当然还有其他方式。但是我们除非为了学习,不然不建议为了用某种鉴权方式和安全措施或者用什么新技术新框架而强行使用,应该根据实际需要在这些机制的原理上做修改和组合,毕竟技术是为业务服务的。


如果觉得本文对你有帮助,可以对博主关注,如果平时不怎么看CSDN的关注人动态,可关注下面公众号,不定期分享一些小demo、小项目以及学习心得
秀宇笔记

往期文章:

在 C# 中调用 AWS API 接口并使用 AWS 鉴权方式,可以通过 AWS SDK for .NET 来实现。以下是一个简单的示例: 1. 首先,需要安装 AWS SDK for .NET。可以通过 NuGet 包管理器来安装。 2. 在代码中引入 AWS SDK 的命名空间: ```csharp using Amazon; using Amazon.Runtime; using Amazon.Runtime.CredentialManagement; using Amazon.S3; using Amazon.S3.Model; ``` 3. 创建 AWS 访问凭证对象。可以使用以下代码从 AWS 访问密钥文件或凭证配置文件中读取访问密钥和秘密访问密钥: ```csharp var options = new CredentialProfileOptions { AccessKey = "YOUR_ACCESS_KEY", SecretKey = "YOUR_SECRET_KEY" }; var profile = new CredentialProfile("profile-name", options); var profileAWSCredentials = new CredentialProfileStoreChain().TryGetAWSCredentials(profile, out var awsCredentials); ``` 4. 创建 AWS S3 客户端对象,并使用上一步中创建的访问凭证对象进行身份验证: ```csharp var region = RegionEndpoint.GetBySystemName("us-west-2"); // 指定 AWS 区域 var s3Client = new AmazonS3Client(awsCredentials, region); ``` 5. 调用 AWS S3 API 接口。以下是一个示例: ```csharp var request = new PutObjectRequest { BucketName = "my-bucket", Key = "my-object", ContentBody = "Hello World!" }; var response = await s3Client.PutObjectAsync(request); ``` 以上代码演示了如何使用 AWS SDK for .NET 调用 AWS S3 API 接口并使用 AWS 鉴权方式进行身份验证。根据实际情况,需要将代码中的访问密钥和秘密访问密钥替换为自己的凭证信息,并将区域、桶名和对象键等参数替换为实际的值。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值