我们好,我是鱼肉,前几日在 地球 里看见了一名爸爸妈妈撷取的该文《API USB结构设计最差课堂教学》,我也读了两遍,写的的确好,给我们撷取呵呵,坚信对后端合作开发的爸爸妈妈会很有协助。
API USB结构设计
译者:InfoQ Man
Token 结构设计
Token 是服务器端聚合的两个个数组,以作应用程序展开允诺的两个副本,当第二次登入后,伺服器聚合两个 Token 便将此 Token 回到给应用程序,之后应用程序只需所带那个 Token 前去允诺统计数据方可,无须再度所带帐号和公钥。
Token 的值通常用 UUID(演算法较为知名的有七彩演算法),当服务器端转交到应用程序允诺后会聚合 Token(两个个字符串,如 etye0fgkgk4ca2ttdsl0ae9a5dd77471fgf),接着将 Token 做为 key 将一些和 Token 关连的重要信息做为 value 留存到如 Redis 内存资料库中,并行把该 Token 回到给应用程序;先期该应用程序的允诺都需要所带那个 Token,伺服器接到允诺后就会去内存伺服器中相匹配那个 Token 与否存有,存有则初始化USB,不存有回到USB严重错误。
Token 类型API Token(USB副本): 通常是把 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 USB结构设计准则
1、明晰协定规范化
在结构设计初期需要明晰双方的通讯协定是 TCP、HTTP、RPC,通常针对较为敏感的交易或者行业(如金融业),建议采用 HTTPS 协定以确保统计数据交互的安全。
2、统一USB路径规范化
建议选用 Restful 的风格,通常选用这样的格式:控制器名/方法名。具体请参考以下例子:
POST /recommend/cardlist
3、统一USB版本管理
APP 后台逻辑总是处于变化当中,但是 APP 端(如安卓和 ios)因为涉及到应用市场的审核问题,还有这些 2C 端的 APP 应用存有版本碎片化的问题,因此后台暴露的USB需要在一段时间内支持不同版本的USB,通常方法是通过 Nginx 通过配置过滤依照USB的不同版本展开路由分发。
通常来说,USB的版本管理通常有以下两种方法:
在 URL 中加入 version 重要信息,如下述;在 HTTP header 加入 version 重要信息,这样就等于只有两个USB,但是具体的不同版本的业务逻辑由后台区分处理。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、为你的USB设定初始化门槛
为初始化你的系统分配两个 ID 和 key,针对每个允诺对 ID 和 key 展开校验,避免在企业内网中的其他系统只要知道USB被可以随意初始化。
5、USB回到规范化
回到统计数据尽量统一规范化,务必包括:回到码、回到重要信息、统计数据。
{
“code” : 0,
“content” : “string”, <- 这里为 JSON
“message” : “string”
}
6、USB安全规范化
当我们合作开发的USB需要暴露到公网,这样的风险跟我们在企业内网暴露给其他系统初始化的风险是不可同日而语的。其中有很多风险需要我们一一解决。以下仅提供能想到的:
6.1.统计数据如何防止被看见?目前业界老生常谈就是对称身份验证和非对称身份验证。
对称身份验证:对称密钥在身份验证和解密的过程中采用的密钥是相同的,常见的对称身份验证演算法有 DES,AES;优点是计算速度快,缺点是在统计数据传送前,发送方和转交方必须商定好秘钥,接着使双方都能留存好秘钥,如果一方的秘钥被泄露,那么身份验证重要信息也就不安全了;
非对称身份验证:服务器端会聚合一对密钥,私钥存放在伺服器端,公钥可以发布给任何人采用;优点就是比起对称身份验证更加安全,但是加解密的速度比对称加密慢太多了;广泛采用的是 RSA 演算法;
目前主流的做法是在传输层采用 https 协定,http 和 tcp 之间添加一层身份验证层(SSL 层),这一层负责统计数据的身份验证和解密。https 协定则是巧妙的利用上述两种对称身份验证方法;浅显一点说就是应用程序和服务器端建立三次握手连接过程中通过交换双方非对称公钥,接著采用对方非对称公钥身份验证双方约定好的对称密钥,这样就只有双方有那个对称密钥(这样的非对称身份验证可以保证很安全的把对称密钥给到对方)。先期双方的报文沟通就可以采用该对称密钥展开加解密(这样的对称身份验证可以保证允诺报文可以快速被解密处理,并在处理后被快速身份验证响应回去)。
6.2.统计数据如何防止给篡改?那个时候我们需要对统计数据展开加签,统计数据亲笔签名平时用得较为多的是 MD5,即将需要提交的统计数据通过某种方式组合和两个数组,接着通过 MD5 聚合一段身份验证数组,这段身份验证数组就是统计数据包的亲笔签名。具体请看以下的图。
如果身份验证统计数据被抓包后被用于重放攻击,我们怎么办?那个时候我们可以把解密后的 URL 模块中的时间戳与系统时间展开较为,如果时间差超过一定间距(如 5 分钟)即认为该报文被劫持并回到严重错误。但是,务必保证该时间戳的超时时间一定要跟 sign 留存的有效时间一致。
应用程序在第二次访问服务器端时,服务器端将 sign 内存到 Redis 中并把有效时间设定为跟时间戳的超时时间一致;如果有人采用同两个 URL 再度访问,如果发现内存伺服器中已经存有了本次的 sign,则拒绝服务;如果在 Redis 中的 sign 失效的情况下,有人采用同两个 URL 再度访问,则会被时间戳超时机制拦截。这样的话,就可以避免 URL 被别人截获后的重放攻击。
整个流程如下:
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 机制、分布式锁、状态机等方案;这里引用呵呵之前看见的一篇该文,写得较为详细:https://blog.csdn.net/u011635492/article/details/81058153
8、USB结构设计的一些最差课堂教学即使回到的 JSON 中某字段没有值(即空值),也一定要回到该字段。同时前端也需做好这类情况的容错处理;针对单页面的多USB允诺,为避免扩大攻击面,建议把多USB逻辑整合到两个USB,两个页面直接初始化该USB,以避免绕过部分USB展开攻击;USB最好支持分页;分页通常有电梯式分页(即一开始算好总页数,优劣也一目了然)和游标式分页(即每次查询会拿上一页的最大的那个 ID 即 cursor 展开查询,这种方式更适合类似以时间为次序条件的互联网单页应用);针对你的USB提前做好限流;通常常用的限流有计数器、副本桶、漏桶这三种。具体请参考USB中的几种 限流实现。API USB管理
一家公司的每个系统都会有各种各样的USB,但是大部分公司,特别是传统行业的公司的所谓USB文档更多是当每个系传统的 word 文本格式,这种传统的格式有着人尽皆知的痛点:
维护不及时;与代码不并行;归档后“便束之高阁”;USB文档跟代码没有互动;文本检索无法建立全局搜索,需要额外借助工具。为了解决上述的问题,需要建立一套行之有效的USB管理体系,该体系的目标是:
能够展开USB文档管理,做为先期的USB治理的其中一部分;能做为USB测试的平台,这样能保证USB跟代码是并行的;支持文本检索。业界有很多不同的 API USB管理平台,如去哪儿网的 YAPI 平台、阿里某团队合作开发的 RAP 平台、Swagger、easyAPI 等等。各位爸爸妈妈可以撷取呵呵自己对这些平台的采用感受~
最终,欢迎我们加入鱼肉的 编程学习圈子 ,和 3000 多名 爸爸妈妈们一同交流学习,向大厂大佬们 1 对 1 提问、跟着鱼肉直播做项目(第二期回放已发布)~
往期推荐
别人看源码,那我也要看!
鱼肉的项目视频被狗曝光了。。。
这代码谁写的,太可怕了!
前后端分离,千万别再搞错了!