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 通过配置过滤根据接口的不同版本进行路由分发。

一般来说,接口的版本管理一般有以下两种方法:

  1. 在 URL 中加入 version 信息,如下述;
  2. 在 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&timestamp=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 文本格式,这种传统的格式有着人尽皆知的痛点:

  1. 维护不及时;
  2. 与代码不同步;
  3. 归档后“便束之高阁”;
  4. 接口文档跟代码没有互动;
  5. 文本检索无法建立全局搜索,需要额外借助工具。

为了解决上述的问题,需要建立一套行之有效的接口管理体系,该体系的目标是:

  1. 能够进行接口文档管理,作为后续的接口治理的其中一部分;
  2. 能作为​​接口测试​​的平台,这样能保证接口跟代码是同步的;
  3. 支持文本检索。

这才叫 API 接口设计!的更多相关文章

  1. atitit.基于http json api 接口设计 最佳实践 总结o7

    atitit.基于http  json  api 接口设计 最佳实践 总结o7 1. 需求:::服务器and android 端接口通讯 2 2. 接口开发的要点 2 2.1. 普通参数 meth,p ...

  2. Java生鲜电商平台-API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)

    Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...

  3. API接口设计之token、timestamp、sign 具体架构与实现(APP/小程序,传输安全)

    Java生鲜电商平台-API接口设计之token.timestamp.sign 具体设计与实现 说明:在实际的业务中,难免会跟第三方系统进行数据的交互与传递,那么如何保证数据在传输过程中的安全呢(防窃 ...

  4. Web API接口设计经验总结

    在Web API接口的开发过程中,我们可能会碰到各种各样的问题,我在前面两篇随笔<Web API应用架构在Winform混合框架中的应用(1)>.<Web API应用架构在Winfo ...

  5. Web API接口设计(学习)

    1.在接口定义中确定MVC的GET或者POST方式 由于我们整个Web API平台是基于MVC的基础上进行的API开发,因此整个Web API的接口,在定义的时候,一般需要显示来声明接口是[HttpG ...

  6. API接口设计

    1.场景描述 比如说我们要做一款APP,需要通过api接口给app提供数据.假设我们是做商城,比如我们卖书的.我们可以想象下这个APP大概有哪些内容: 1)首页:banner区域(可以是一些热门书籍的 ...

  7. 优秀的API接口设计原则及方法(转)

    一旦API发生变化,就可能对相关的调用者带来巨大的代价,用户需要排查所有调用的代码,需要调整所有与之相关的部分,这些工作对他们来说都是额外的.如果辛辛苦苦完成这些以后,还发现了相关的bug,那对用户的 ...

  8. php后台对接ios,安卓,API接口设计和实践完全攻略,涨薪必备技能

    2016年12月29日13:45:27    关于接口设计要说的东西很多,可能写一个系列都可以,vsd图都得画很多张,但是由于个人时间和精力有限,所有有些东西后面再补充   说道接口设计第一反应就是r ...

  9. 微信小程序的Web API接口设计及常见接口实现

    微信小程序给我们提供了一个很好的开发平台,可以用于展现各种数据和实现丰富的功能,通过小程序的请求Web API 平台获取JSON数据后,可以在小程序界面上进行数据的动态展示.在数据的关键 一环中,我们 ...

  10. API 接口设计中 Token 类型的分类与设计

    在实际的网站设计中我们经常会遇到用户数据的验证和加密的问题,如果实现单点,如果保证数据准确,如何放着重放,如何防止CSRF等等 其中,在所有的服务设计中,都不可避免的涉及到Token的设计. 目前,基 ...

随机推荐

  1. Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log、App、徽章、插画、头像场景生成,各种风格选择:科技风、运动风

    Midjourney|文心一格prompt教程[Text Prompt(上篇)]:品牌log.App.徽章.插画.头像场景生成,各种风格选择:科技风.运动风 1.撰写 Text Prompt 注意事项 ...

  2. ET介绍——组件式设计(优化版的ECS)

    组件式设计 在代码复用和组织数据方面,面向对象可能是大家第一反应.面向对象三大特性继承,封装,多态,在一定程度上能解决不少代码复用,数据复用的问题.不过面向对象不是万能的,它也有极大的缺陷: 1. 数 ...

  3. INFINI Labs 产品更新 | Console 新增数据比对、新增数据看板表格组件及支持下钻功能等

    INFINI Labs 产品更新啦~,本次产品版本更新包括 Gateway v1.14.0.Console v1.2.0.Easysearch v1.1.1 等,其中 Console 在上一版基础上做 ...

  4. Windows/Linux 下功能强大的桌面截图软件

    说到桌面截图软件,很多人首先想到的是 QQ 自带的截图,或者更高级功能更强大的 Snipaste 截图工具. 独立版本的 QQ 截图至少我目前没找到官方正式的下载链接,默认需要安装和打开 QQ 才能使 ...

  5. WPF中实现含有中心点Slider双向滑动条

    想要实现的效果 原生滑动条 需要认识一下滑动条的组成 在原生控件中生成"资源字典"对应的样式 然后在track所在的列进行添砖加瓦 由于track在row="1" ...

  6. [Java SE] 彻底搞懂Java程序的三大参数配置途径:系统变量与JVM参数(VM Option)/环境变量/启动程序参数args

    0 序言 一次没搞懂,处处受影响.这个问题属于基础问题,但又经常踩坑,不得不重视一下了. 1 Java程序动态参数的配置途径:系统变量与JVM参数(VM Option) vs 环境变量 vs 启动程序 ...

  7. Docusaurus之markdown文档的vscode代码片段

    需求 我是使用Docusaurus建立的个人站点,在写文档是总是要在开头配置作者.日期等等,用过Docusaurus的都应该知道. 因为每次新建一个md文档都需要重新配置,很麻烦,于是我就想能不能新建 ...

  8. .NET周报 【6月第3期 2023-06-18】

    国内文章 揭秘 Task.Wait https://www.cnblogs.com/eventhorizon/p/17481757.html Task.Wait 是 Task 的一个实例方法,用于等待 ...

  9. 第一章 : Linux入门

    1. 概述 ‍ ​​ ‍ 2. Linux 和 Windows 区别 ‍ ​​ ‍ 3. Centos 下载地址 ‍ 网易镜像:http://mirrors.163.com/centos/7/isos ...

  10. Apple、AWS 这些科技巨头,已悄然入局隐私计算

    随着数字化时代的到来,数据已经成为企业竞争的重要资源.然而,与此同时,数据隐私泄露的风险也在不断增加,这已经成为了公共安全和个人权利保护的重要问题.为了解决这个问题,科技巨头谷歌.苹果.亚马逊纷纷入局 ...