一、接口设计原则
-
RESTful风格
- 资源使用名词复数形式:
/api/v1/users
- HTTP方法对应操作类型:
GET /users # 查询列表 POST /users # 创建资源 GET /users/{id} # 查询单个 PUT /users/{id} # 全量更新 PATCH /users/{id}# 局部更新 DELETE /users/{id} # 删除
- 资源使用名词复数形式:
-
版本控制
- 路径包含版本号:
/api/v1/resource
- 请求头携带版本:
X-API-Version: 1.0
- 路径包含版本号:
二、传参方式与注解
传参类型 | 适用场景 | 注解 | 示例 |
---|---|---|---|
路径参数 | 资源唯一标识 | @PathVariable | /users/{userId} |
查询参数 | 过滤/分页/排序 | @RequestParam | ?page=1&size=20 |
请求体 | 复杂数据提交 | @RequestBody | JSON格式数据 |
表单参数 | application/x-www-form-urlencoded | @RequestParam | 传统表单提交 |
请求头 | 认证/设备信息 | @RequestHeader | Authorization: Bearer xxx |
三、参数校验规范
-
基础校验注解
public class UserDTO { @NotBlank(message = "用户名不能为空") @Size(min = 2, max = 20, message = "用户名长度2-20字符") private String username; @Email(message = "邮箱格式错误") private String email; @Min(value = 18, message = "年龄需满18岁") @Max(value = 100, message = "年龄不超过100岁") private Integer age; }
-
级联校验
@PostMapping("/orders") public ResponseEntity<?> createOrder(@Valid @RequestBody OrderCreateDTO dto) { // 自动触发OrderCreateDTO内部嵌套对象的校验 }
-
自定义校验
@Target({FIELD}) @Retention(RUNTIME) @Constraint(validatedBy = PhoneValidator.class) public @interface ValidPhone { String message() default "手机号格式错误"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
四、注释规范
-
Swagger注解
@ApiOperation(value = "创建用户", notes = "需提供用户名、邮箱等基本信息") @PostMapping public UserVO createUser( @ApiParam(value = "用户DTO", required = true) @Valid @RequestBody UserDTO dto) { // 实现逻辑 }
-
方法注释
/** * 根据ID查询用户详情 * @param userId 用户唯一标识符(UUID格式) * @return 用户详细信息视图对象 * @throws ResourceNotFoundException 当用户不存在时抛出 */ @GetMapping("/{userId}") public UserVO getUserById(@PathVariable UUID userId) { // 实现逻辑 }
五、参数类型规范
-
时间格式
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime;
-
枚举参数
public enum OrderStatus { CREATED, PAID, DELIVERED, COMPLETED } @GetMapping("/orders") public List<OrderVO> getOrdersByStatus( @RequestParam OrderStatus status) { // 自动转换枚举值 }
-
文件上传
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public String handleFileUpload( @RequestPart("file") @Valid @Size(max = 5*1024*1024) MultipartFile file) { // 文件大小限制5MB }
六、安全规范
- 敏感参数(如密码)必须使用POST请求体传输
- 路径参数需做权限校验,确保数据归属
- 列表查询必须包含分页参数(page/size)
- 批量操作需增加防重放机制(如timestamp+nonce)
为批量操作增加防重放机制可通过以下步骤实现,结合时间戳与随机数双重验证:
1. 请求参数构造
客户端每次请求需携带:
timestamp
:当前UTC时间戳(精确到毫秒)nonce
:16字节以上随机字符串(建议使用加密安全方法生成)
2. 服务端验证流程
from datetime import datetime, timedelta
import redis # 使用Redis存储临时nonce
def verify_request(req_timestamp, req_nonce):
# 时间窗口校验(示例设置5分钟)
now = datetime.utcnow().timestamp()
if abs(now - req_timestamp) > 300: # 300秒=5分钟
return False
# Nonce唯一性校验
r = redis.Redis()
if r.exists(f'nonce:{req_nonce}'):
return False
r.setex(f'nonce:{req_nonce}', 300, '1') # 设置5分钟过期
return True
3. 数学验证模型
设合法请求时间窗口为$T$,随机数空间为$N$,攻击成功率: $$P = \frac{q}{N} \times \frac{\Delta t}{T}$$ 其中:
- $q$: 攻击请求次数
- $\Delta t$: 时间同步误差
- 当$N \geq 2^{128}$且$T \leq 300s$时,可实现极高安全性
4. 增强措施
- 时间戳加密传输:使用HMAC签名防止篡改 $$signature = HMAC_SHA256(secret_key, timestamp|nonce)$$
- 滑动窗口机制:动态调整时间窗口阈值
- 分布式锁:确保集群环境下的nonce校验一致性
5. 实施注意事项
- 客户端与服务端时钟需保持同步(建议使用NTP协议)
- 随机数生成应使用安全熵源(如
os.urandom()
) - 建议配合HTTPS防止中间人攻击
该方案通过时空双重验证,可有效防御重放攻击,同时保证系统吞吐量。时间窗口与随机数长度的选择需根据具体业务场景的安全要求进行调整。
七、最佳实践示例
@RestController
@RequestMapping("/api/v1/products")
@Api(tags = "商品管理接口")
public class ProductController {
@GetMapping("/{productId}")
@ApiOperation("获取商品详情")
public ProductDetailVO getProductDetail(
@PathVariable @ApiParam("商品ID") Long productId,
@RequestParam(required = false)
@ApiParam("语言代码(zh-CN/en-US)") String lang) {
// 实现逻辑
}
@PostMapping
@ApiOperation("创建新商品")
public ResponseEntity<ProductVO> createProduct(
@Valid @RequestBody ProductCreateDTO dto,
@RequestHeader("X-User-Id") Long userId) {
// 实现逻辑
}
}
八、错误响应规范
{
"timestamp": "2023-08-20T15:00:00Z",
"status": 400,
"code": "INVALID_PARAMETER",
"message": "用户名长度不符合要求",
"path": "/api/v1/users",
"details": [
{
"field": "username",
"message": "长度必须介于2到20个字符之间"
}
]
}
注:建议配合使用SpringDoc OpenAPI(原Swagger)自动生成接口文档,通过
@ParameterObject
注解支持参数对象文档生成。