这才叫 API 接口设计!
API 接口设计
Token 设计
Token 是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个 Token 便将此 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次带上用户名和密码。
Token 的值一般用 UUID(算法比较著名的有雪花算法),当服务端接收到客户端请求后会生成 Token(一串字符,如 etye0fgkgk4ca2ttdsl0ae9a5dd77471fgf),然后将 Token 作为 key 将一些和 Token 关联的信息作为 value 保存到如 Redis 缓存数据库中,同步把该 Token 返回给客户端;后续该客户端的请求都需要带上这个 Token,服务器收到请求后就会去缓存服务器中匹配这个 Token 是否存在,存在则调用接口,不存在返回接口错误。
Token 种类
API Token(接口令牌): 一般用于访问不需要用户登录的接口,如登录、注册、一些基本数据的获取(如信用卡官网的如信用卡费率相关信息)等。获取接口令牌需要拿 appId、timestamp 和 sign 来换;其中该 sign 值一般是把 timestamp、key 和对应的参数先进行字母排序再进行 MD5 加密(有时候会加盐),即 sign=MD5(排序(timestamp+key+参数));
- 假设 API 的请求参数为 channel:T,discount:90%,quantities:10,根据参数名称的 ASCII 码表的顺序排序即为:channel:T,discount:90%,quantities:10。
- 接着把排序后的参数名和参数值拼装在一起为:channelTdiscount90%quantities10。
- 把拼装好的字符串采用 utf-8 编码,使用签名算法对编码后的字节流进行摘要,即为 sign=md5(channelTdiscount90%quantities10);
- 最后,Token=hex(appid+sign+timestamp+salt),即可获得十六进制的一串字符,如“68656C6C6F776F726C64”。
USER Token(用户令牌): 用于访问需要用户登录之后的接口,如:获取我的基本信息、保存、修改、删除等操作。获取用户令牌需要拿用户名和密码来换。
API 接口设计原则
1、明确协议规范
在设计初期需要明确双方的通讯协议是 TCP、HTTP、RPC,一般针对比较敏感的交易或者行业(如金融业),建议使用 HTTPS 协议以确保数据交互的安全。
2、统一接口路径规范
建议采用 Restful 的风格,一般采用这样的格式:控制器名/方法名。具体请参考以下例子:
POST /recommend/cardlist
3、统一接口版本管理
APP 后台逻辑总是处于变化当中,但是 APP 端(如安卓和 ios)因为涉及到应用市场的审核问题,还有这些 2C 端的 APP 应用存在版本碎片化的问题,因此后台暴露的接口需要在一段时间内支持不同版本的接口,一般方法是通过 Nginx 通过配置过滤根据接口的不同版本进行路由分发。
一般来说,接口的版本管理一般有以下两种方法:
- 在 URL 中加入 version 信息,如下述;
- 在 HTTP header 加入 version 信息,这样就等于只有一个接口,但是具体的不同版本的业务逻辑由后台区分处理。
POST v1/recommend/cardlist
Nginx的路由分发:
server {
listen 80;
server_name vip.com;
location /v1/ {
proxy_pass http://129.0.0.1:8001/;
proxy_redirect http://129.0.0.1:8001/ /v1/;
proxy*set*header Host $host;
}
location /v2/ {
proxy_pass http://129.0.0.1:8002/;
proxy_redirect http://129.0.0.1:8002/ /v2/;
proxy*set*header Host $host;
}
}
server {
listen 8001;
allow 129.0.0.1;
deney all;
server_name vip.com;
root vip.com/v1/;
}
server {
listen 8002;
allow 129.0.0.1;
deney all;
server_name vip.com;
root vip.com/v2/;
}
4、为你的接口设定调用门槛
为调用你的系统分配一个 ID 和 key,针对每个请求对 ID 和 key 进行校验,避免在企业内网中的其他系统只要知道接口被可以随意调用。
5、接口返回规范
返回数据尽量统一规范,务必包括:返回码、返回信息、数据。
{
"code" : 0,
"content" : "string", <- 这里为 JSON
"message" : "string"
}
6、接口安全规范
当我们开发的接口需要暴露到公网,这样的风险跟我们在企业内网暴露给其他系统调用的风险是不可同日而语的。其中有很多风险需要我们一一解决。以下仅提供能想到的:
6.1.数据如何防止被看到?
目前业界老生常谈就是对称加密和非对称加密。
对称加密:对称密钥在加密和解密的过程中使用的密钥是相同的,常见的对称加密算法有 DES,AES;优点是计算速度快,缺点是在数据传送前,发送方和接收方必须商定好秘钥,然后使双方都能保存好秘钥,如果一方的秘钥被泄露,那么加密信息也就不安全了;
非对称加密:服务端会生成一对密钥,私钥存放在服务器端,公钥可以发布给任何人使用;优点就是比起对称加密更加安全,但是加解密的速度比对称加密慢太多了;广泛使用的是 RSA 算法;
目前主流的做法是在传输层使用 https 协议,http 和 tcp 之间添加一层加密层(SSL 层),这一层负责数据的加密和解密。https 协议则是巧妙的利用上述两种对称加密方法;浅显一点说就是客户端和服务端建立三次握手连接过程中通过交换双方非对称公钥,接着使用对方非对称公钥加密双方约定好的对称密钥,这样就只有双方有这个对称密钥(这样的非对称加密可以保证很安全的把对称密钥给到对方)。后续双方的报文沟通就可以使用该对称密钥进行加解密(这样的对称加密可以保证请求报文可以快速被解密处理,并在处理后被快速加密响应回去)。
6.2.数据如何防止给篡改?
这个时候我们需要对数据进行加签,数据签名平时用得比较多的是 MD5,即将需要提交的数据通过某种方式组合和一个字符串,然后通过 MD5 生成一段加密字符串,这段加密字符串就是数据包的签名。具体请看以下的图。

6.3.时间戳机制
如果加密数据被抓包后被用于重放攻击,我们怎么办?这个时候我们可以把解密后的 URL 参数中的时间戳与系统时间进行比较,如果时间差超过一定间距(如 5 分钟)即认为该报文被劫持并返回错误。但是,务必保证该时间戳的超时时间一定要跟 sign 保存的有效时间一致。
客户端在第一次访问服务端时,服务端将 sign 缓存到 Redis 中并把有效时间设定为跟时间戳的超时时间一致;如果有人使用同一个 URL 再次访问,如果发现缓存服务器中已经存在了本次的 sign,则拒绝服务;如果在 Redis 中的 sign 失效的情况下,有人使用同一个 URL 再次访问,则会被时间戳超时机制拦截。这样的话,就可以避免 URL 被别人截获后的重放攻击。
整个流程如下:
1、客户端通过用户名密码登录服务器并获取 Token
2、客户端生成时间戳 timestamp,并将 timestamp 作为其中一个参数
3、客户端将所有的参数,包括 Token 和 timestamp 按照自己的算法进行排序加密得到签名 sign
4、将 token、timestamp 和 sign 作为请求时必须携带的参数加在每个请求的 URL 后边(http://url/request?token=123×tamp=123&sign=123123123)
5、服务端写一个过滤器对 token、timestamp 和 sign 进行验证,只有在 token 有效、timestamp 未超时、缓存服务器中不存在 sign 三种情况同时满足,本次请求才有效。
6.4.随机数机制
另外,一般会在 URL 参数上加上随机数(即所谓的加盐)并与 6.3 的时间戳机制组合使用以便提升防重复提交攻击。
6.5.黑名单机制
针对同一个 IP 在短时间内频繁请求的,可以通过 Nginx 进行过滤,同步可以在 Nginx 部署动态黑名单(即 IP 实时更新到黑名单库),这样可以防控少量的 DDOS。但受限于判断黑名单需要考虑多维度的信息,一般我们的 Nginx 尽量只做同一 IP 校验,更多维度的黑名单校验可以通过厂商去解决。
6.6.数据合法性校验
这里的数据合法性校验主要指的是数据格式校验和业务规则校验。
- 数据格式校验:日期格式校验、长度校验、非空校验等;
- 业务规则校验:如库存校验、身份证合法性校验等。
7、幂等性
定义:在计算机中,表示对同一个过程应用相同的参数多次和应用一次产生的效果是一样,这样的过程即被称为满足幂等性。
具体的解决方案有 token 机制、分布式锁、状态机等方案;
8、接口设计的一些最佳实践
- 即使返回的 JSON 中某字段没有值(即空值),也一定要返回该字段。同时前端也需做好这类情况的容错处理;
- 针对单页面的多接口请求,为避免扩大攻击面,建议把多接口逻辑整合到一个接口,一个页面直接调用该接口,以避免绕过部分接口进行攻击;
- 接口最好支持分页;分页一般有电梯式分页(即一开始算好总页数,优劣也一目了然)和游标式分页(即每次查询会拿上一页的最大的那个 ID 即 cursor 进行查询,这种方式更适合类似以时间为排序条件的互联网单页应用);
- 针对你的接口提前做好限流;一般常用的限流有计数器、令牌桶、漏桶这三种。具体请参考接口中的几种 限流实现。
API 接口管理
一家公司的每个系统都会有各种各样的接口,但是大部分公司,特别是传统行业的公司的所谓接口文档更多是当每个系传统的 word 文本格式,这种传统的格式有着人尽皆知的痛点:
- 维护不及时;
- 与代码不同步;
- 归档后“便束之高阁”;
- 接口文档跟代码没有互动;
- 文本检索无法建立全局搜索,需要额外借助工具。
为了解决上述的问题,需要建立一套行之有效的接口管理体系,该体系的目标是:
- 能够进行接口文档管理,作为后续的接口治理的其中一部分;
- 能作为接口测试的平台,这样能保证接口跟代码是同步的;
- 支持文本检索。
这才叫 API 接口设计!的更多相关文章
- atitit.基于http json api 接口设计 最佳实践 总结o7
atitit.基于http json api 接口设计 最佳实践 总结o7 1. 需求:::服务器and android 端接口通讯 2 2. 接口开发的要点 2 2.1. 普通参数 meth,p ...
- Java生鲜电商平台-API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)
Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...
- API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)
Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...
- Web API接口设计经验总结
在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...
- Web API接口设计(学习)
1.在接口定义中确定MVC的GET或者POST方式 由于我们整个Web API平台是基于MVC的基础上进行的API开发,因此整个Web API的接口,在定义的时候,一般需要显示来声明接口是[HttpG ...
- API接口设计
1.场景描述 比如说我们要做一款APP,需要通过api接口给app提供数据.假设我们是做商城,比如我们卖书的.我们可以想象下这个APP大概有哪些内容: 1)首页:banner区域(可以是一些热门书籍的 ...
- 优秀的API接口设计原则及方法(转)
一旦API发生变化,就可能对相关的调用者带来巨大的代价,用户需要排查所有调用的代码,需要调整所有与之相关的部分,这些工作对他们来说都是额外的.如果辛辛苦苦完成这些以后,还发现了相关的bug,那对用户的 ...
- php后台对接ios,安卓,API接口设计和实践完全攻略,涨薪必备技能
2016年12月29日13:45:27 关于接口设计要说的东西很多,可能写一个系列都可以,vsd图都得画很多张,但是由于个人时间和精力有限,所有有些东西后面再补充 说道接口设计第一反应就是r ...
- 微信小程序的Web API接口设计及常见接口实现
微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,通过小程序的请求Web API 平台获取JSON数据后,可以在小程序界面上进行数据的动态展示.在数据的关键 一环中,我们 ...
- API 接口设计中 Token 类型的分类与设计
在实际的网站设计中我们经常会遇到用户数据的验证和加密的问题,如果实现单点,如果保证数据准确,如何放着重放,如何防止CSRF等等 其中,在所有的服务设计中,都不可避免的涉及到Token的设计. 目前,基 ...
随机推荐
- Linux修改Python软链接
Linux修改python软链接 0. 适用场景及基础知识 适用场景: 有些自带的是python3命令,嫌输入太麻烦,可以修改成python命令 有些自带是python是python2,想修改成pyt ...
- pnpm才是前端工程化项目的未来
前言 相信小伙伴们都接触过npm/yarn,这两种包管理工具想必是大家工作中用的最多的包管理工具,npm作为node官方的包管理工具,它是随着node的诞生一起出现在大家的视野中,而yarn的出现则是 ...
- Electron-ChatGPT桌面端ChatGPT实例|electron25+vue3聊天AI模板EXE
基于electron25+vite4+vue3仿制chatgpt客户端聊天模板ElectronChatGPT. electron-chatgpt 使用最新桌面端技术Electron25.x结合Vite ...
- 不同大小的缓冲区对 MD5 计算速度的影响
最*需要在计算大文件的 MD5 值时显示进度,于是我写了如下的代码: public long Length {get; private set; } public long Position { ge ...
- 20200630 excel365 选中一个单元格,对应的行和列都高亮
Excel默认只高亮选中单元格的行标和列标,在整理数据时容易眼花,如能把这一行和列都高亮岂不是更好.方法在此: 1 打开"开发工具"菜单 默认这一项是隐藏的.文件-选项-自定义功能 ...
- Dotnet9网站回归Blazor重构,访问速度飞快,交互也更便利了!
大家好,我是沙漠尽头的狼. Dotnet9网站回归Blazor重构,访问速度确实飞快,同时用上Blazor的交互能力,站长也同步添加了几个在线工具,这篇文章分享下Blazor的重构过程,希望对大家网站 ...
- 用R语言实现并行计算:基于R的数据处理和分析工具
目录 引言 随着数据量的爆炸式增长,数据处理和分析的需求也越来越大.传统的批处理计算已经无法满足高效的数据处理和分析需求,因此,并行计算成为了一个重要的技术方向.然而,R语言作为一种开源.可视化能力强 ...
- 大语言模型(LLM)在文本分类、语言生成和文本摘要中的应用
目录 大语言模型(LLM)在文本分类.语言生成和文本摘要中的应用 引言 文本分类.语言生成和文本摘要是人工智能领域中的重要任务,涉及到自然语言处理.机器学习和深度学习等领域.本文将介绍大语言模型(LL ...
- 2021/1/10例会 academy of management journal 2014vol 57 No.2,484-514
这次的论文由于考试周的原因看的不是很细,但大概还是浏览过一遍了.然后这次我的拓展又神奇的匹配到了教授想让我们接下来想看的论文. perfect! 但不足的是,没有进行相关论文的检索,自己的拓展没有理论 ...
- 从零玩转SpringBoot3-快速入门
一.简介 1.前置知识 ● Java17 ● Spring.SpringMVC.MyBatis ● Maven.IDEA 2.环境要求 环境&工具 版本(or later) Spr ...