为什么 auth-middleware 和 permission-middleware 是分开的?
| 中间件 | 回答的问题 | 英文术语 | 文件位置 |
|---|---|---|---|
auth-middleware.js |
"你是谁?" | Authentication(认证) | backend/auth/ |
permission-middleware.js |
"你能做什么?" | Authorization(授权) | backend/middleware/ |
// 只需要认证,不需要权限检查
router.get('/api/me/profile',
authMiddleware, // ✅ 只要登录就能看自己的资料
getMyProfile
);
// 需要认证 + 权限
router.post('/api/appointments',
authMiddleware, // ✅ 先确认身份
requirePermission('appointments:create'), // ✅ 再检查权限
createAppointment
);
// 公开 API,都不需要
router.get('/api/public/services',
// 无中间件
getPublicServices
);
permission-middleware 需要知道用户是谁才能查权限表:
// auth-middleware 执行后,req.user 包含:
req.user = {
id: 'user-123',
role: 'manager',
tenantId: 'tenant_qqnails',
jobTitleId: 'jt-456'
};
// permission-middleware 用这些信息去查:
// 1. role_permissions 表(角色权限)
// 2. job_title_permissions 表(职位权限)
// 3. employee_special_permissions 表(特殊授权/拒绝)
修改 JWT 验证逻辑不会影响权限逻辑,反之亦然。
// 可选认证(有 token 就解析,没有也放行)
router.get('/api/products', optionalAuth, getProducts);
// 任一权限即可
router.get('/api/reports/summary',
authMiddleware,
requireAnyPermission(['reports:view', 'dashboard:view']),
getReportSummary
);
// 必须同时拥有多个权限
router.delete('/api/employees/:id',
authMiddleware,
requireAllPermissions(['employees:delete', 'hr:manage']),
deleteEmployee
);
// 假设合并成一个中间件
function authAndPermission(permission) {
return (req, res, next) => {
// 1. JWT 验证逻辑
// 2. 用户状态检查
// 3. 权限查询逻辑
// 4. 权限计算逻辑
// ❌ 问题:不需要权限检查的 API 也被迫传参数
// ❌ 问题:代码臃肿,难以测试
// ❌ 问题:违反关注点分离原则
}
}
// 用起来很别扭
router.get('/api/me/profile', authAndPermission(null), ...); // 被迫传 null
| 框架/语言 | 认证 | 授权 | 是否分离 |
|---|---|---|---|
| Spring Security (Java) | AuthenticationFilter | AuthorizationFilter | ✅ 分离 |
| Django (Python) | AuthenticationMiddleware | @permission_required | ✅ 分离 |
| ASP.NET Core (C#) | Authentication | Authorization | ✅ 分离 |
| Express.js (Node) | passport / jwt-middleware | rbac / permission-middleware | ✅ 分离 |
这是经典的 Authentication vs Authorization 分离模式:
几乎所有成熟的后端框架都采用这种设计,因为它符合单一职责原则,提供更好的灵活性和可维护性。
更新于 2026-02-01 | Celoria 开发笔记