一个好的 API 设计能让前后端协作事半功倍,而一个糟糕的 API 设计则会让整个团队陷入无尽的沟通和返工中。本文将系统梳理 RESTful API 的设计规范、版本管理策略和 Token 认证授权体系。
RESTful API 的核心原则
1. 用名词而非动词表示资源
// 正确:资源导向\nGET /api/users # 获取用户列表\nGET /api/users/123 # 获取单个用户\nPOST /api/users # 创建用户\nPUT /api/users/123 # 完整更新用户\nPATCH /api/users/123 # 部分更新用户\nDELETE /api/users/123 # 删除用户\n\n// 错误:动作导向(RPC 风格)\nGET /api/getUsers\nPOST /api/createUser\nPOST /api/deleteUser2. 利用 HTTP 方法表达操作语义
| 方法 | 语义 | 幂等性 | 安全性 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 完整替换 | 是 | 否 |
| PATCH | 部分更新 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
3. 子资源嵌套
GET /api/users/123/orders # 用户 123 的订单列表\nGET /api/users/123/orders/456 # 用户 123 的订单 456\nPOST /api/users/123/orders # 为用户 123 创建订单4. 查询参数:过滤、排序、分页
GET /api/users?status=active&page=2&size=20&sort=createdAt,desc&search=john统一响应格式设计
// 成功响应\n{\n "code": 200,\n "message": "success",\n "data": { "id": 1, "name": "张三" },\n "timestamp": 1751700000000\n}\n\n// 分页响应\n{\n "code": 200,\n "message": "success",\n "data": {\n "list": [...],\n "total": 156,\n "page": 2,\n "size": 20,\n "totalPages": 8\n }\n}\n\n// 错误响应\n{\n "code": 40001,\n "message": "用户名已存在",\n "data": null,\n "timestamp": 1751700000000\n}HTTP 状态码的语义化使用
200 OK # GET/PUT 成功\n201 Created # POST 创建成功(配合 Location 头返回新资源 URL)\n204 No Content # DELETE 成功,无返回内容\n400 Bad Request # 请求参数错误\n401 Unauthorized # 未认证(未登录或 Token 无效)\n403 Forbidden # 已认证但无权限\n404 Not Found # 资源不存在\n409 Conflict # 资源冲突(如用户名已存在)\n422 Unprocessable # 请求格式正确但语义错误\n429 Too Many # 频率限制\n500 Internal Error # 服务器内部错误API 版本管理策略
方案对比
| 方案 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| URL 路径 | /api/v1/users | 直观、易缓存 | URL 变化 |
| 请求头 | Accept: vnd.example.v1+json | URL 不变 | 不直观、难调试 |
| 查询参数 | /api/users?version=1 | 容易切换 | 污染 URL |
推荐:URL 路径版本——最直观,对前端最友好。
Token 认证授权体系
OAuth 2.0 的四种授权模式
授权码模式(Authorization Code):最安全,适合有后端的 Web 应用。用户重定向到认证服务器 → 获取授权码 → 用授权码换取 Token。
密码模式(Resource Owner Password):用户直接提供用户名密码换取 Token。仅适用于高度信任的第一方应用。
客户端凭证模式(Client Credentials):服务间调用。用 client_id + client_secret 换取 Token。
隐式模式(Implicit):已废弃,不再推荐。
RBAC(基于角色的访问控制)实践
// SpringBoot 方法级权限控制\n@RestController\n@RequestMapping("/api/admin")\npublic class AdminController {\n\n @PreAuthorize("hasRole('ADMIN')")\n @GetMapping("/users")\n public Result listUsers() { /* ... */ }\n\n @PreAuthorize("hasAnyRole('ADMIN', 'MANAGER')")\n @PutMapping("/users/{id}")\n public Result updateUser(@PathVariable Long id) { /* ... */ }\n\n @PreAuthorize("@permissionService.canDeleteUser(#id)")\n @DeleteMapping("/users/{id}")\n public Result deleteUser(@PathVariable Long id) { /* ... */ }\n}Token 刷新策略(生产环境关键)
// 双 Token 机制\nPOST /api/auth/login\n// 返回:\n{\n "accessToken": "eyJ...(15分钟后过期)",\n "refreshToken": "eyJ...(7天后过期)"\n}\n\n// 无感刷新\nPOST /api/auth/refresh\nBody: { "refreshToken": "eyJ..." }\n// 返回新的 accessToken(refreshToken 可以同时轮换)API 安全最佳实践
- HTTPS 强制:所有 API 通信必须走 HTTPS,防止中间人攻击。
- 请求频率限制(Rate Limiting):防止暴力破解和 DDoS 攻击。
- 输入校验:永远不信任客户端输入,服务端必须进行严格的参数校验。
- 敏感数据脱敏:密码、身份证号等敏感数据在日志和响应中脱敏。
- CORS 白名单:只允许可信域名的跨域请求。
- SQL 注入防护:使用参数化查询(MyBatis #{} 而非 ${})。
总结
RESTful API 设计的核心不在于是否严格遵循了所有规范,而在于一致性——整个项目的 API 应该有统一的命名风格、统一的响应格式、统一的错误处理。一个"不那么 RESTful 但完全一致"的 API 远比一个"部分 RESTful 部分混乱"的 API 更好维护。
评论 (0)