【项目开发Tip】精通接口设计:从规范到安全的全方位解析

写在前面 / 链接存档

导读

  • 在前后端项目开发中,接口设计不仅是连接前后端的桥梁,更是保证系统稳定性、安全性和可维护性的关键环节。

  • 设计一个高效、规范且安全的接口,对于开发者而言至关重要。

  • 以下将深入剖析接口设计的全流程,从后端开发流程接口设计规范,再到接口的安全处理,全方位无死角地解读接口设计的奥秘。

一、接口设计规范

设计优秀接口的首要任务:详尽的需求分析

  • 只有深刻理解了业务需求,我们才能全面地规划接口设计,包括接口的基本定义安全性考量以及幂等性处理等多个方面。

需求分析

  • 在接到开发任务后,关键是快速掌握相关模块和业务,依赖原型文档和PRD文档(产品学徒抬头.gif)

  • 若缺少原型图,与产品经理紧密沟通至关重要→尤其是在需求变更时,通过深入沟通确保全面理解新要求

  • 后端人员的开发流程↓

    需要熟悉接口设计处于开发的什么阶段

后端人员开发流程

接口设计之前的关键点

  • 通读当前业务的 PRD 文档
  • 通读当前业务的原型文档
  • 不断地频繁地与产品沟通,直到搞清楚业务为止
  • 后期与前端联调的重要依据

接口四要素

接口设计是后端开发中的关键环节

规范的接口设计可以提高系统的可维护性和可扩展性

接口设计应包含以下四大要素

  • 请求路径:以模块名称进行区分(英文),通俗易懂
  • 请求方式:符合RESTful风格,查询使用GET,新增使用POST,修改使用PUT,删除使用DELETE
  • 接口入参:包括路径参数、问号传参和请求体参数
    • 路径参数使用@PathVariable注解接收
    • 问号传参使用后端形参或类中的属性接收
    • 请求体参数使用JSON对象
    • 后端使用DTO(@RequestBody)接收
  • 接口出参:统一格式{code:200, msg:"成功", data:{}},数据封装为VO,过滤敏感数据,整合数据

接口设计-一个例子

  • 接口地址/nursing_project
  • 请求方式GET
  • 请求参数
参数名称参数说明数据类型
name护理项目名称string
status状态(0:禁用,1:启用)int
pageNum当前页码int
pageSize每页显示条数int
  • 响应示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
"code"200,
"msg""操作成功",
"data"{
"total""19",
"pageSize"10,
"pages""2",
"page"1,
"records"[
{
"id""1",
"createTime""2023-09-26 15:08:59",
"updateTime""2023-10-28 01:59:27",
"createBy""1671403256519078153",
"creator""行政专员",
"name""翻身拍背",
"orderNo"1,
"unit""次",
"price"30.00,
"image""https://yjy-slwl-0ss.oss-cn-hangzhou.aliyuncs.com/424a475d-76b1-4c57-b430-60293901ef79.jpg",
"nursingRequirement""帮助患者翻身,并进行背部按摩,以促进血液循环",
"status"0,
"count"2
}
]
"operationTime"null
}

接口测试

编写完接口,需要用接口工具进行测试

常见的接口测试工具:

  • Postman
  • Apifox
  • Swagger 在线接口文档
  • Knife4j(wagger的增强版,可生成离线接口文档)

使用这些工具测试接口时,需要知道明确的接口信息

二、接口的安全

参数校验

  • 入参出参校验是每个程序员必备的基本素养。你设计的接口,必须先校验参数
  • 比如入参是否允许为空、入参长度要求、入参是否在枚举值范围内等等。
  • 日常开发中,很多低级bug都是不校验参数导致的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Override
public ResponseResult delPicture(Integer id) {
// 1.检查参数
if (id == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
}

WmMaterial wmMaterial = getById(id);
if (wmMaterial == null) {
return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
}

// 2.判断当前素材是否被应用
Integer count = wmNewsMaterialMapper.selectCount(Wrappers.<WmNewsMaterial>lambdaQuery().eq(WmNewsMaterial::getId, id));
if (count > 0) {
return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "当前素材被引用,不能删除");
}

//3.删除OSS中的图片
fileStorageService.delete(wmMaterial.getUrl());

//4.删除数据库中的素材信息
removeById(id);
return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}
  • 除了手动添加参数校验外,还可以使用Springboot Validation框架对参数进行校验

  • 如下代码↓ 如果是非空校验,则可以直接使用注释表示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Data
public class WmLoginDto {
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
private String name;

/**
* 密码
*/
@NotBlank(message = "密码不能为空")
private String password;
}

三、更安全的接口

在现代应用系统中,接口安全至关重要,特别是在处理敏感数据和对外提供服务时。我们面临的场景包括:

  • 内部管理系统:依赖token验证和Spring Security进行权限控制。
  • 对外接口服务:需要数据加密、HTTPS通信、加签验签以及限流措施,
  • 面向消费者的接口:实施token验证和限流策略。

数据加密

对于对外提供的接口服务,敏感数据(如手机号、邮箱、身份证号、密码等)必须加密处理,以满足网络安全和监管要求。

对称加密

对称加密

  • 优点:加密速度快,适合大量数据处理。
  • 缺点:密钥管理复杂,一旦泄露,安全性将大打折扣。
  • 应用:适用于非持久化存储的敏感信息加密

非对称加密

非对称加密

使用Https协议

HTTPS通过SSL / TLS协议确保数据传输的安全性、完整性和身份认证。

HTTPS证书需从可信的云平台(如阿里云、腾讯云)购买,以确保通信安全。

Https是安全性也是通过对称加密和非对称加密来完成的

  • 详细的交互流程如下图:

使用Https协议加密的交互流程

执行过程

  1. 身份验证:客户提交身份证明文件给服务提供商,后者验证后颁发包含公钥A和公司信息的数字整数
  2. 证书验证:客户使用数字整数访问网站,客户端验证证书合法性。若合法,提取公钥A并生成随机密钥KEY
  3. 数据传输:客户端使用私钥B加密KEY,服务器用私钥B解密获取KEY。双方随后使用KEY进行对称加密通信,确保数据安全

限流

接口限流可防止服务过载、抵御恶意攻击、提升服务质量、保护后端服务及时应对突发流量。

通过限制请求次数,保护服务器资源,确保系统稳定性。

限流措施包括:基于Tomcat限流、令牌桶算法、漏桶算法,分别适用于不同业务场景

Tomcat 限流

  • 方式:设置最大连接数

  • 应用:适用于单体项目,集群环境下最多支持5台

  • Tomcat限流算法

    • 可以设置tomcat的最大连接数进行限流
    • tomcat中的配置文件server.xml中,找到如下配置,可以修改maxThreads="200"来设置连接数
1
2
3
4
5
6
<Connector port="8080"
protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443"
maxThreads="200"
acceptCount="100" />

漏桶算法

  • 原理:基于IP限制请求速率,超出桶容量的请求将被丢弃

  • 优点:简单易用,能有效控制请求速率

  • Nginx漏桶算法

    • 漏桶算法(Leaky Bucket)是一种常用的流量控制算法,广泛应用于网络流量整形和速率限制。
    • 其原理类似于一个装水的桶,桶底有一个固定速率的孔,水(请求)从桶顶注入,并以恒定速率从桶底流出。当注入的水量超过桶的容量时,多余的水会溢出(丢弃)

Nginx漏桶算法实现原理

桶的容量:代表当前系统或队列能够处理的请求数的上限

流出速率:桶底的孔以固定的速率排出请求,表示系统处理请求的能力

溢出:如果请求到达的速率超过了桶的流出速率,并且桶已满,则多余的请求将被丢弃

  • 漏桶算法可以根据用户的IP进行限流,可以设置每秒访问的请求数,我们可以配合nginx来完成漏桶算法
1
2
3
4
5
6
7
8
9
10
11
12
http {
limit_req_zone $binary_remote_addr zone=serviceRateLimit:10m rate=10r/s;
server {
listen 80;
server_name localhost;

location / {
limit_req zone=serviceRateLimit burst=20 nodelay;
proxy_pass http://targetserver;
}
}
}

语法:limit_ req_zone key zone rate

  • key:定义限流对象,binary remote addr就是一种key,基于客户端ip限流
  • Zone:定义共享存储区来存储访问信息,10m可以存储16wip地址访问信息
  • Rate:最大访问速率,rate=10r/s 表示每秒最多请求10个请求
  • burst=20:相当于桶的大小
  • Nodelay:快速处理

令牌桶算法

  • 原理:令牌以固定速率生成,请求消耗令牌,无令牌时请求被延迟或丢弃

  • 优点:既能控制平均速率,又能应对突发流量

  • 实现:Spring Cloud Gateway、Sentinel 等组件支持

  • 令牌桶算法通过维护一个“桶”来控制数据的发送速率。

    • 桶内存储一定数量的“令牌”,每个令牌代表一个数据包的发送权限或一定量数据的处理能力。
    • 令牌以固定的速率生成,并添加到桶中。
    • 数据包的发送需要消耗令牌,如果桶内没有令牌,则数据包需要等待,直到有令牌可用

令牌桶算法示意图

  • 令牌桶:一个虚拟的容器,用来存放固定数量的令牌。桶的大小(即容量)决定了系统可以累积的令牌数量,从而决定了系统能够应对的最大突发流量。
  • 令牌填充速率:系统以固定的速率向桶中添加令牌。这个速率决定了系统允许的平均流量速率。增加令牌生成速率可以提高系统的平均处理速率,但也可能导致更多的突发流量。
  • 令牌消耗:每当一个数据包发送时,就从桶中移除一定数量的令牌。令牌的数量与数据包的大小相关,通常一个令牌代表一个字节或固定大小的数据包。如果桶中没有令牌,数据包将被延迟发送或丢弃,直到桶中有足够的令牌。
  • 可解决突发流量
  • 令牌桶算法可以使用Spring Cloud Gateway网关中的局部过滤实现

END

本文深入剖析了:【接口设计的全流程】,从**【规范】【安全】,再到【限流策略】**,为开发者提供了全面的指导。

接口设计的四大要素和测试方法确保了接口的高效与稳定。

同时,参数校验、数据加密、HTTPS通信安全措施进一步提升了接口的可靠性。

未来,接口设计将更加注重用户体验和安全性,如引入更智能的限流算法、加强身份验证等,以应对日益复杂的网络环境。

  • Copyrights © 2024-2025 brocademaple
  • 访问人数: | 浏览次数:

      请我喝杯咖啡吧~

      支付宝
      微信