侧边栏壁纸
  • 累计撰写 28 篇文章
  • 累计收到 1 条评论

前后端交互规范

2023-11-11 / 0 评论 / 181 阅读

一、协作流程规范


在团队协作中,每个人都会提交git commit message,但是由于每个人的开发风格和书写习惯的不同,导致git提交五花八门,不利于维护和阅读。一般来说,大厂都一套自己的代码提交规范的,尤其是在开源项目中,代码提交规范都是一致的。

1、需求分析。确保大家对需求有一致的认知
2、设计接口文档。前端需要确认是否符合要求
3、并行开发。前端需要根据接口文档进行Mock, 模拟对接后端接口;联调之前,要求后端做好接口测试
4、真实环境联调。前端将接口请求代理到后端服务,进行真实环境联调。

二、接口规范


2.1 接口风格:

RESTful —— 推荐
JSONRPC
2.1.1 RESTful

标准格式

http(s)://server.com/app-name/{version}/{domain}/{rest-convention}
用法

GET
GET /api/teams (对应团队列表)

GET /api/teams/123 (对应 ID 为 123 的团队)

GET /api/teams/123/members (对应 ID 为 123 的团队下的成员列表)

GET /api/teams/123/members/456 (对应 ID 为 123 的团队下 ID 为 456 的成员)

POST
用于创建资源,或者特殊资源提交(如文件上传/下载)

POST /api/teams/123/members/456 (新增ID 为 123 的团队下 ID 为 456 的成员信息)

body参数{name:'xxx'}

POST /api/teams/123/members/456 (下载ID 为 123 的团队下 ID 为 456 的成员信息)

POST /api/teams/123/members/456 (上传ID 为 123 的团队下 ID 为 456 的成员信息)

body参数{file:formData}

UPDATE(PUT和PATCH)
PUT 用于更新资源的全部信息,在请求的 body 中需要传入修改后的全部资源主体
PATCH 用于局部更新,在 body 中只需要传入需要改动的资源字段。

POST /api/teams (创建团队)

POST /api/teams/123/members (创建团队ID 为 123 的成员)

PUT /api/teams/123/members/456 (更新ID 为 123 的团队下 ID 为 456 的成员全部信息)

PATCH /api/teams/123/members/456 (更新ID 为 123 的团队下 ID 为 456 的成员部分信息)

DELETE
// 单个删除

DELETE /api/users/123

// 批量删除

DELETE /api/users

body参数{ids:[]}

HEAD
获取一个资源的元数据,如数据的哈希值或最后的更新时间。

OPTIONS
获取客户端能对资源做什么操作的信息

过滤
?limit=10:指定返回记录的数量

?offset=10:指定返回记录的开始位置。

?page=2&size=100:指定第几页,以及每页的记录数。

?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。

?keyname=1:指定筛选条件复制代码

其他规范:
规则1:URI结尾不应包含(/)
规则2:正斜杠分隔符(/)必须用来指示层级关系
规则3:应使用连字符(-)来提高URI的可读性
规则4:不得在URI中使用下划线(_)
规则5:URI路径中全都使用小写字母

2.2 注意点:

明确数据类型。例如数字应为Int或Float类型,而非String类型
明确空值的意义。比如在做更新操作时,空值是表示重置,还是忽略更新
明确默认值。对象类型的返回空对象{}, 数组类型的返回空数组[],字符串类型的返回空字符串"",Number和Boolean类型的返回null
对于大数字(如Java的long 类型,整数类型大于16位浮点数类型大于18位),返回给前端时需要设置为字符串类型, 防止js发生溢出
关于日期时间格式
对于需要前端再次处理的日期值, 可以使用时间戳
对于纯展示用的日期值, 推荐返回格式化文本, 例如: 2017年1月1日或2017-01-01 20:00:00
对于日期时间需要排序时,返回时间戳或者格式化的包含毫秒数的文本
建议同时返回时间戳的原始值(或 ISO 标准格式)和用于统一显示的格式化文本,例如: {"createTime": 1543195480357, "createTimeText": "2018年11月26日"}
关于分页
分页计数,从1开始
避免滚动加载可能出现的重复数据,采用 lastId 分页方式
图片URL
图片的 URL 建议返回完整的 URL,协议为HTTP时可省略协议
文件上传/下载
文件上传限制默认最大为10M
文件上传类型默认支持:
文档类:doc、docx、xls、xlsx、ppt、pptx、pdf、txt
图片类:jpg、jpeg、png、gif
其他:zip、rar
多文件上传不支持IE9及以下版本浏览器
图片上传服务器前需先在前端压缩,默认控制在400万以下像素或2560*1440及以下分辨率
响应避免冗余的嵌套
接口版本化,保持向下兼容;接口不兼容时需升级版本
建议使用Swagger等工具,避免人工维护可能导致的代码和文档不同步
鉴权通过header实现
同时给出 ID 字段和用于显示字段时,前端提交只提交ID字段
2.3 接口文档规范

后端通过接口文档向前端暴露接口相关的信息。通常需要包含这些信息:

版本号
文档描述
服务的入口,例如协议、域名、基本路径
测试服务器,可选
简单使用示例
安全和认证
具体接口定义
方法名称或者URI
方法描述
请求参数及其描述,必须说明类型(数据类型、是否可选等)
响应参数及其描述, 必须说明类型(数据类型、是否可选等)
可能的异常情况、错误代码、以及描述
请求示例,可选
2.3.1 Header

Content-Type
application/json 默认
application/x-www-form-urlencoded 表单提交/APP请求
Authorization
Basic XXXXXXXX
Bearer XXXXXXXX
Cookie
openid = hash(appid+uid)
Expires 过期时间,默认为0
Referer 之前页面URL,跳转第三方地址需要此参数
lang 多语言
zh_cn
zh_hk
en_us
2.3.2 请求参数

4种类型:
1、cookie: 一般用于OAuth认证
2、Request Header: 一般用于OAuth认证
3、请求body数据
4、地址栏参数: 详见【2.1.1过滤】

2.3.3 响应参数

response Demo

  • 表示不必须
    {

    status: 200, // 详见【status】

    data: {

    code: 10000, // 返回码,详见【4.3.2 公共响应参数】

    msg: '成功', // * 返回码描述

    sub_code: 'success', // 明细返回码

    sub_msg: '', // * 明细返回码描述,显示给客户端用户【须语义化中文提示】,code不为10000时均需toast提示

    sysMsg: '', // * 提示,调试使用,可包括中英文数字及特殊符号

    result: [], // 返回的数据结果对象,可根据需要定义

    page: {

    current: 1,           // * 当前页,从1开始
    
    size: 10,             // * 每页记录数
    
    total: 100            // * 总记录数

    }

    },

    message: '成功', // 提示,显示给客户端用户【须语义化中文提示】

    sysMessage: 'success' // * 提示,调试使用,中英文都行

}

2.4 转义与编码

编码规则:encodeURIComponent 与 decodeURIComponent

URI特殊字符需转义
特殊字符及转义符号

特殊字符

转义后的符号

+

%2B

空格

%20

/

%2F

?

%3F

%

%25

#

%23

&

%26

=

%3D

!

%21

第三方回调页面URI需反转义,如:支付宝支付成功回调页面

URI汉字需转为Unicode码
2.5 加密

首选HTTPS,其中以下项目要求必须为HTTPS
APP
微信公众号和小程序
使用第三方API(如海康、高德等)
HTTP项目需要对关键敏感信息进行加密处理,HTTPS项目不做要求
账号、密码
账号、密码禁止明文传输,如admin等
密码加密策略:
方法一
服务器端存储密码为Hash(Random-Salt + Hash(Constant-SALT + Pasword))
客户端传输密码为Hash(Constant-SALT + Password)
Random-Salt为用户的随机盐,每个用户均不同,服务器端收到客户端的hash密码后,在将其与用户随机盐一起Hash运算,从而将结果与数据库存储值相比较。
优点:数据库存储的密码经过两层哈希,且其中包含了固定盐和用户随机盐,安全性较高。
缺点:客户端传输的密码虽然经过了一层哈希,但是使用固定盐值,因此相同密码生成的结果均一致,容易收到重放攻击。
方法二
服务器端存储密码为Hash(Constant-SALT + Pasword)
客户端传输密码为Hash(Random-Salt + Hash(Constant-SALT + Password))
Random-Salt为每次进入登陆页面时生成的随机盐,此处主要是为了防止重放攻击,作用类似与nonce 服务器收到客户端上传的hash之后的密码,根据用户ID取出服务器存储的密码,并通过与之前返回客户端的Random-Salt(可存储于Session中)进行Hash运算,从而与客户端上传的密码进行比较。
优点:客户端有效的防止了重放攻击。
缺点:在前端代码中,固定盐值暴露,一旦后台数据库被攻破,用户密码信息将有危险。
加密库:
MD5
crypto-js
手机号、银行卡号、姓名等私密信息
通用加密策略:
Hash(Constant-SALT + Pasword)
Random-Salt为每个应用or业务系统的随机盐,与其他细节加密字段进行Hash运算后再跳转。
数字加密策略:
转换进制,如:
// 加密

const mask = (+phone).toString(28)

// 解密

const phone = parseInt(mask, 28)

手机号、银行卡号加密策略:
方法一
参考上文数字加密策略
方法二
参考上文通用加密策略
姓名、邮箱、住址等加密策略:
参考上文通用加密策略
第三方跳转时URI加密
加解密策略
参考上文通用加密策略
2.6 跨域

CORS 实现

三、接口测试与模拟

3.1 工具:

RESTful
Swagger 这是最为接近上面理想模型的一个解决方案
JSON Server 快速生成JSON mock服务器
Easy Mock 可视化的、在线的接口mock服务
Yapi接口平台 支持本地部署
GraphQl
GraphQL Faker
graphql-tools
模拟数据生成
js 强大的模拟数据生成工具,支持Node和浏览器
js 数据生成和模拟工具

四、 附录

4.1 公共状态码(status)


扫描二维码,在手机上阅读