@GetMapping("/detail")
public ProjectDTO detail(@RequestParam Long id) {
LoginUser user = SecurityContext.getCurrentUser();
return projectService.getDetail(id);
}
public OrderDTO detail(Long orderId, Long userId) {
Order order = orderMapper.selectOne(
new QueryWrapper<Order>()
.eq("id", orderId)
.eq("user_id", userId)
.eq("deleted", 0)
);
if (order == null) {
throw new BizException("资源不存在或无权限访问");
}
return convert(order);
}
-- 常见用于定位资源归属字段的思路
SELECT table_name, column_name
FROM information_schema.columns
WHERE column_name IN ('user_id','owner_id','creator_id','tenant_id','dept_id','org_id');
第二步:按接口操作类型检查
对每类资源,建议按操作类型建立检查清单:
操作类型
常见风险点
审计关注点
详情查询
按 id 直接查询
是否带 user_id、tenant_id、dept_id 等约束
更新操作
先查后改时只校验存在性
修改前是否确认资源归属
删除操作
逻辑删除直接按 id
删除条件是否包含权限范围
导出下载
导出接口复用管理员查询
是否继承当前用户数据权限
批量操作
只校验部分 id
是否对所有 id 做权限校验
第三步:关注批量接口
批量接口经常被忽略,例如:
POST /api/file/delete
{"ids":[101,102,103]}
危险写法:
public void deleteFiles(List<Long> ids) {
fileMapper.deleteBatchIds(ids);
}
更合理的方式是先按当前用户权限范围查询可操作资源,再比较数量或直接按权限条件删除:
public void deleteFiles(List<Long> ids, Long userId) {
int count = fileMapper.countByIdsAndOwner(ids, userId);
if (count != ids.size()) {
throw new BizException("部分资源不存在或无权限操作");
}
fileMapper.deleteByIdsAndOwner(ids, userId);
}
SQL 层也应保持约束:
UPDATE file
SET deleted = 1
WHERE id IN (?, ?, ?)
AND owner_id = ?
AND deleted = 0;
第四步:检查间接对象访问
有些接口不是直接传资源 id,而是传 fileKey、uuid、taskNo、shareCode、downloadToken 等间接标识。审计时不要因为参数不是自增 id 就降低警惕。
推荐意见