瞧瞧别人家的API接口,那叫一个优雅

前言

在实际工作中,我们需要经常跟第三方平台打交道,可能会对接第三方平台API接口,或者提供API接口给第三方平台调用。

那么问题来了,如果设计一个优雅的API接口,能够满足:安全性、可重复调用、稳定性、好定位问题等多方面需求?

今天跟大家一起聊聊设计API接口时,需要注意的一些地方,希望对你会有所帮助。

1. 签名

为了防止API接口中的数据被篡改,很多时候我们需要对API接口做签名

接口请求方将请求参数 + 时间戳 + 密钥拼接成一个字符串,然后通过md5等hash算法,生成一个前面sign。

然后在请求参数或者请求头中,增加sign参数,传递给API接口。

API接口的网关服务,获取到该sign值,然后用相同的请求参数 + 时间戳 + 密钥拼接成一个字符串,用相同的m5算法生成另外一个sign,对比两个sign值是否相等。

如果两个sign相等,则认为是有效请求,API接口的网关服务会将给请求转发给相应的业务系统。

如果两个sign不相等,则API接口的网关服务会直接返回签名错误。

问题来了:签名中为什么要加时间戳?

答:为了安全性考虑,防止同一次请求被反复利用,增加了密钥没破解的可能性,我们必须要对每次请求都设置一个合理的过期时间,比如:15分钟。

这样一次请求,在15分钟之内是有效的,超过15分钟,API接口的网关服务会返回超过有效期的异常提示。

目前生成签名中的密钥有两种形式:

一种是双方约定一个固定值privateKey。

另一种是API接口提供方给出AK/SK两个值,双方约定用SK作为签名中的密钥。AK接口调用方作为header中的accessKey传递给API接口提供方,这样API接口提供方可以根据AK获取到SK,而生成新的sgin。

2. 加密

有些时候,我们的API接口直接传递的非常重要的数据,比如:用户的银行卡号、转账金额、用户身份证等,如果将这些参数,直接明文,暴露到公网上是非常危险的事情。

由此,我们需要对数据进行加密

目前使用比较多的是用BASE64加解密。

我们可以将所有的数据,安装一定的规律拼接成一个大的字符串,然后在加一个密钥,拼接到一起。

然后使用JDK1.8之后的Base64工具类处理,效果如下:

【加密前的数据】www.baidu.com
【加密后的数据】d3d3LmJhaWR1LmNvbQ==

为了安全性,使用Base64可以加密多次。

API接口的调用方在传递参数时,body中只有一个参数data,它就是base64之后的加密数据。

API接口的网关服务,在接收到data数据后,根据双方事先预定的密钥、加密算法、加密次数等,进行解密,并且反序列化出参数数据。严格来说base64只能算是编码方式。

3. ip白名单

为了进一步加强API接口的安全性,防止接口的签名或者加密被破解了,攻击者可以在自己的服务器上请求该接口。

需求限制请求ip,增加ip白名单

只有在白名单中的ip地址,才能成功请求API接口,否则直接返回无访问权限。

ip白名单也可以加在API网关服务上。

但也要防止公司的内部应用服务器被攻破,这种情况也可以从内部服务器上发起API接口的请求。

这时候就需要增加web防火墙了,比如:ModSecurity等。

4. 限流

如果你的API接口被第三方平台调用了,这就意味着着,调用频率是没法控制的。

第三方平台调用你的API接口时,如果并发量一下子太高,可能会导致你的API服务不可用,接口直接挂掉。

由此,必须要对API接口做限流

限流方法有三种:

  1. 对请求ip做限流:比如同一个ip,在一分钟内,对API接口总的请求次数,不能超过10000次。

  2. 对请求接口做限流:比如同一个ip,在一分钟内,对指定的API接口,请求次数不能超过2000次。

  3. 对请求用户做限流:比如同一个AK/SK用户,在一分钟内,对API接口总的请求次数,不能超过10000次。

我们在实际工作中,可以通过nginxredis或者gateway实现限流的功能。

5. 参数校验

我们需要对API接口做参数校验,比如:校验必填字段是否为空,校验字段类型,校验字段长度,校验枚举值等等。

这样做可以拦截一些无效的请求。

比如在新增数据时,字段长度超过了数据字段的最大长度,数据库会直接报错。

但这种异常的请求,我们完全可以在API接口的前期进行识别,没有必要走到数据库保存数据那一步,浪费系统资源。

有些金额字段,本来是正数,但如果用户传入了负数,万一接口没做校验,可能会导致一些没必要的损失。

还有些状态字段,如果不做校验,用户如果传入了系统中不存在的枚举值,就会导致保存的数据异常。

由此可见,做参数校验是非常有必要的。

在Java中校验数据使用最多的是hiberateValidator框架,它里面包含了@Null、@NotEmpty、@Size、@Max、@Min等注解。

用它们校验数据非常方便。

当然有些日期字段和枚举字段,可能需要通过自定义注解的方式实现参数校验。

6. 统一返回值

我之前调用过别人的API接口,正常返回数据是一种json格式,比如:

{"code":0,"message":null,"data":[{"id":123,"name":"abc"}]
},

签名错误返回的json格式:

{"code":1001,"message":"签名错误","data":null
}

没有数据权限返回的json格式:

{"rt":10,"errorMgt":"没有权限","result":null
}

这种是比较坑的做法,返回值中有多种不同格式的返回数据,这样会导致对接方很难理解。

出现这种情况,可能是API网关定义了一直返回值结构,业务系统定义了另外一种返回值结构。如果是网关异常,则返回网关定义的返回值结构,如果是业务系统异常,则返回业务系统的返回值结构。

但这样会导致API接口出现不同的异常时,返回不同的返回值结构,非常不利于接口的维护。

其实这个问题我们可以在设计API网关时解决。

业务系统在出现异常时,抛出业务异常的RuntimeException,其中有个message字段定义异常信息。

所有的API接口都必须经过API网关,API网关捕获该业务异常,然后转换成统一的异常结构返回,这样能统一返回值结构。

7. 统一封装异常

我们的API接口需要对异常进行统一处理。

不知道你有没有遇到过这种场景:有时候在API接口中,需要访问数据库,但表不存在,或者sql语句异常,就会直接把sql信息在API接口中直接返回。

返回值中包含了异常堆栈信息数据库信息错误代码和行数等信息。

如果直接把这些内容暴露给第三方平台,是很危险的事情。

有些不法分子,利用接口返回值中的这些信息,有可能会进行sql注入或者直接脱库,而对我们系统造成一定的损失。

因此非常有必要对API接口中的异常做统一处理,把异常转换成这样:

{"code":500,"message":"服务器内部错误","data":null
}

返回码code500,返回信息message服务器内部异常

这样第三方平台就知道是API接口出现了内部问题,但不知道具体原因,他们可以找我们排查问题。

我们可以在内部的日志文件中,把堆栈信息、数据库信息、错误代码行数等信息,打印出来。

我们可以在gateway中对异常进行拦截,做统一封装,然后给第三方平台的是处理后没有敏感信息的错误信息。

8. 请求日志

在第三方平台请求你的API接口时,接口的请求日志非常重要,通过它可以快速的分析和定位问题。

我们需要把API接口的请求url、请求参数、请求头、请求方式、响应数据和响应时间等,记录到日志文件中。

最好有traceId,可以通过它串联整个请求的日志,过滤多余的日志。

当然有些时候,请求日志不光是你们公司开发人员需要查看,第三方平台的用户也需要能查看接口的请求日志。

这时就需要把日志落地到数据库,比如:mongodb或者elastic search,然后做一个UI页面,给第三方平台的用户开通查看权限。这样他们就能在外网查看请求日志了,他们自己也能定位一部分问题。

9. 幂等设计

第三方平台极有可能在极短的时间内,请求我们接口多次,比如:在1秒内请求两次。有可能是他们业务系统有bug,或者在做接口调用失败重试,因此我们的API接口需要做幂等设计

也就是说要支持在极短的时间内,第三方平台用相同的参数请求API接口多次,第一次请求数据库会新增数据,但第二次请求以后就不会新增数据,但也会返回成功。

这样做的目的是不会产生错误数据。

我们在日常工作中,可以通过在数据库中增加唯一索引,或者在redis保存requestId和请求参来保证接口幂等性。

10. 限制记录条数

对于对我提供的批量接口,一定要限制请求的记录条数

如果请求的数据太多,很容易造成API接口超时等问题,让API接口变得不稳定。

通常情况下,建议一次请求中的参数,最多支持传入500条记录。

如果用户传入多余500条记录,则接口直接给出提示。

建议这个参数做成可配置的,并且要事先跟第三方平台协商好,避免上线后产生不必要的问题。

11. 压测

上线前我们务必要对API接口做一下压力测试,知道各个接口的qps情况。

以便于我们能够更好的预估,需要部署多少服务器节点,对于API接口的稳定性至关重要。

之前虽说对API接口做了限流,但是实际上API接口是否能够达到限制的阀值,这是一个问号,如果不做压力测试,是有很大风险的。

比如:你API接口限流1秒只允许50次请求,但实际API接口只能处理30次请求,这样你的API接口也会处理不过来。

我们在工作中可以用jmeter或者apache benc对API接口做压力测试。

12. 异步处理

一般的API接口的逻辑都是同步处理的,请求完之后立刻返回结果。

但有时候,我们的API接口里面的业务逻辑非常复杂,特别是有些批量接口,如果同步处理业务,耗时会非常长。

这种情况下,为了提升API接口的性能,我们可以改成异步处理

在API接口中可以发送一条mq消息,然后直接返回成功。之后,有个专门的mq消费者去异步消费该消息,做业务逻辑处理。

直接异步处理的接口,第三方平台有两种方式获取到。

第一种方式是:我们回调第三方平台的接口,告知他们API接口的处理结果,很多支付接口就是这么玩的。

第二种方式是:第三方平台通过轮询调用我们另外一个查询状态的API接口,每隔一段时间查询一次状态,传入的参数是之前的那个API接口中的id集合。

13. 数据脱敏

有时候第三方平台调用我们API接口时,获取的数据中有一部分是敏感数据,比如:用户手机号、银行卡号等等。

这样信息如果通过API接口直接保留到外网,是非常不安全的,很容易造成用户隐私数据泄露的问题。

这就需要对部分数据做数据脱敏了。

我们可以在返回的数据中,部分内容用星号代替。

已用户手机号为例:182****887

这样即使数据被泄露了,也只泄露了一部分,不法分子拿到这份数据也没啥用。

14. 完整的接口文档

说实话,一份完整的API接口文档,在双方做接口对接时,可以减少很多沟通成本,让对方少走很多弯路。

接口文档中需要包含如下信息:

  1. 接口地址

  2. 请求方式,比如:post或get

  3. 请求参数和字段介绍

  4. 返回值和字段介绍

  5. 返回码和错误信息

  6. 加密或签名示例

  7. 完整的请求demo

  8. 额外的说明,比如:开通ip白名单。

接口文档中最好能够统一接口和字段名称的命名风格,比如都用驼峰标识命名。

接口地址中可以加一个版本号v1,比如:v1/query/getCategory,这样以后接口有很大的变动,可以非常方便升级版本。

统一字段的类型和长度,比如:id字段用Long类型,长度规定20。status字段用int类型,长度固定2等。

统一时间格式字段,比如:time用String类型,格式为:yyyy-MM-dd HH:mm:ss。

接口文档中写明AK/SK和域名,找某某单独提供等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4115.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶代客泊车AVP摄像头与ECU交互需求规范

目录 1 文档范围及控制方法... 5 1.1 目的.... 5 1.2 文档授权... 5 1.3 文档变更管理... 5 1.4 缩写.... 5 1.5 术语.... 5 2 系统组成... 6 2.1 系统框图... 6 2.2 电源供应和时序要求... 7 2.2.1 摄像头供电控制... 7 2.2.2 摄像头上电时序要求…

【产品经理】TO B市场分析

市场分析是一个独立而又宏大的学科领域,并且具体使用中,目标和个体不同,分析的方式方法也不同。TO B产品的市场分析是对市场环境、市场规模、性质、特征、竞品进行分析,从而寻找和研究潜在需求的市场机会,帮助产品经理…

[洛谷]P8662 [蓝桥杯 2018 省 AB] 全球变暖(dfs)

读题不规范&#xff0c;做题两年半&#xff01; 注意&#xff1a;被海水淹没后的陆地应用另一个字符表示&#xff0c;而不是把它变为海洋&#xff0c;这个点可以便利&#xff0c;但不能被当作起点&#xff0c;不然就只有 36 分。 ACocde: #include<bits/stdc.h> using…

浅谈无人机遥感图像拼接与处理方法

遥感&#xff08;RS-Remote Sensing&#xff09;——不接触物体本身&#xff0c;用传感器收集目标物的电磁波信息&#xff0c;经处理、分析后&#xff0c;识别目标物&#xff0c;揭示其几何、物理性质和相互关系及其变化规律的现代科学技术。 换言之&#xff0c;即是“遥远的感…

opencv -13 掩模

什么是掩膜&#xff1f; 在OpenCV中&#xff0c;掩模&#xff08;mask&#xff09;是一个与图像具有相同大小的二进制图像&#xff0c;用于指定哪些像素需要进行操作或被考虑。掩模通常用于选择特定区域或进行像素级别的过滤操作。 OpenCV 中的很多函数都会指定一个掩模&…

【Express.js】基于业务特性的分布式结构

基于业务特性的分布式结构 上节的mvc架构&#xff0c;把所有不同模块的同层文件都放在一个目录下 我们也可以将你的项目结构按照业务模块进行划分&#xff0c;每一个模块内可以再按mvc分层&#xff0c;或者不分&#xff0c;这样子把不同模块独立出来的就叫做分布式结构(dcs) …

2. CSS3的新特性

2.1 CSS3的现状 ●新增的CSS3特性有兼容性问题, ie9才支持 ●移动端支持优于PC端 ●不断改进中 ●应用相对广泛 ●现阶段主要学习: 新增选择器和盒子模型以及其他特性 CSS3给我们新增了选择器,可以更加便捷,更加自由的选择目标元素&#xff1a; 1.属性选择器 2.结构伪类选择器…

js常用功能方法

一. 从0~9十个数字中随机选出5个数 function randomFive(){var arr [0,1,2,3,4,5,6,7,8,9];var out [];var num 5;while(out.length < num){var temp (Math.random()*arr.length) >> 0;out.push(arr.splice(temp,1));}return out}二. JS去掉字符串前后空格或去掉…

【详细介绍分析golang中map的相关知识】

golang-map 定义和初始化操作和访问添加和修改元素删除元素获取元素判断键是否存在遍历map 常见应用场景 Golang中的map是一种非常强大和灵活的数据结构&#xff0c;它可以用来存储键值对。在本文中&#xff0c;我们将深入探讨Golang中map的相关知识&#xff0c;包括其定义、初…

1.7 运维可以转行什么

文章目录 运维可以转行什么1. 云计算与DevOps2. 信息安全3. 数据分析与大数据4. 项目管理5. 咨询与培训结论 运维可以转行什么 运维&#xff08;Operations and Maintenance&#xff0c;简称O&M&#xff09;是信息技术领域中的重要职能&#xff0c;负责管理和维护企业的信…

代码随想录一刷day50

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、力扣123.买卖股票的最佳时机III二、力扣● 188.买卖股票的最佳时机IV 前言 一、力扣123.买卖股票的最佳时机III class Solution {public int maxProfit(i…

拖动排序功能的实现 - 使用HTML、CSS和JavaScript

引言 在现代Web应用程序中&#xff0c;拖动排序是一种常见的用户界面交互方式&#xff0c;它允许用户通过拖动元素来重新排列列表或项目的顺序。本文将介绍如何使用HTML、CSS和JavaScript来实现手动拖动排序功能。 一、HTML结构 首先&#xff0c;我们需要定义一个列表&#…

电子病历编辑器源码

电子病历系统采取结构化与自由式录入的新模式&#xff0c;自由书写&#xff0c;轻松录入。化实现病人医疗记录&#xff08;包含有首页、病程记录、检查检验结果、医嘱、手术记录、护理记录等等。&#xff09;的保存、管理、传输和重现&#xff0c;取代手写纸张病历。不仅实现了…

利用深度学习进行黑白照片着色:使用 Keras 构建 GAN 进行照片自动上色的详细实践指南

利用深度学习进行黑白照片着色&#xff1a;使用 Keras 构建 GAN 进行照片自动上色的实践指南 在这篇博客文章中&#xff0c;我们将探讨一个具有挑战性的问题&#xff0c;即如何利用深度学习自动为黑白照片上色。传统的图片上色过程是一个艰苦且劳动密集型的过程&#xff0c;必…

Cannot get a STRING value from a NUMERIC cell

Cannot get a STRING value from a NUMERIC cell 错误一&#xff1a; 导入Excel表格数据&#xff0c;该列设置数据类型为String&#xff0c;输入数据是int类型 解决方法&#xff1a;cell.setCellType(CellType.STRING); 错误二&#xff1a;日期类型需要定义格式 解决方法如下&a…

朝花夕拾 - 2023 精神错乱记录

jsliang 的精神错乱记录&#xff0c;一点 2023 小思考。 也许我们曾偏离航道&#xff0c;但请不要放弃抵达终点 前言 在 2020.11 过来珠海&#xff0c;来到金山工作 2 年半的时间里&#xff1a; 在工作上&#xff0c;更换了 3 个小团队&#xff0c;达到了每年一换在工作上&…

autok3s k3d rancher研究

参考 功能介绍 | Rancher文档AutoK3s 是用于简化 K3s 集群管理的轻量级工具&#xff0c;您可以使用 AutoK3s 在任何地方运行 K3s 服务。http://docs.rancher.cn/docs/k3s/autok3s/_index 什么是 AutoK3s k3s是经过完全认证的 Kubernetes 产品&#xff0c;在某些情况下可以替…

沉淀自己的pro-table组件,并发布到npm(Vue3、element-plus)

文章目录 沉淀自己的pro-table组件&#xff0c;并发布到npmQuick Start开发过程笔记add TS Support 参考资料 沉淀自己的pro-table组件&#xff0c;并发布到npm 传送门 约定&#xff1a;npm包名vue3-el-pro-table&#xff0c;引用vue3-el-pro-table的包名为“本项目”。 声明…

Oracle EBS 客制化AP发票无法验证和关联交易的AR事务处理无法创建

背景: 在某项目上,国外账套上线以后,国外法人所有单据使用英文(US);涉及关联交易时,如国外公司使用英文环境创建AP发票,国内公司使用中文环境创建AR事务处理。 问题症状: 1、客制化AP发票接口API采用异步方式处理,每次从客制化AP发票接口表中取一定记录条数批量处理,…

iOS开发 - appstore评价与app内展示appstore

iOS开发 - appstore评价与app内展示appstore 之前开发中遇到app内通过广告直接展示某个app的appstore信息页面。StoreKit提供了SKStoreProductViewController可以app中直接访问app store 而不需要跳转到app store 一、代码实现 #import "SDStoreProductManager.h"…