横向越权:修改参数访问不属于自己的数据
一、什么是横向越权
定义
横向越权(Horizontal Privilege Escalation)是指 同一权限级别的用户,通过篡改请求参数或资源标识,访问本不属于自己的数据或功能。
例子
假设一个在线商城,用户 A 访问订单详情的 URL:
GET /order/detail?orderId=1001
如果用户 B 把 orderId
改成 1001
也能访问到 A 的订单,这就是 横向越权漏洞。
与纵向越权的区别
横向越权:同级别用户之间的权限越界(普通用户访问到其他普通用户的数据)。
纵向越权:低级别用户访问到高级别功能(普通用户访问到管理员功能)。
二、Spring Boot 项目中横向越权的常见场景
参数直接控制资源 ID
例如:
/api/user/info?id=123
如果系统只根据
id
查询数据库,而不验证当前用户是否有权限访问该 ID,对方就能访问别人的信息。
仅靠前端控制访问
比如前端菜单隐藏了“管理员功能”,但后端 API 并没有权限验证。
依赖会话中的用户 ID 不严谨
有些开发会直接从请求参数中取 userId,而不是 session/JWT 中的用户身份。
三、Spring Boot 中防止横向越权的常用方案
1. 基于用户身份的后端校验(强制访问控制)
无论前端传什么参数,后端必须根据当前登录用户验证资源归属。
示例:
@GetMapping("/order/detail")
public Order getOrderDetail(@RequestParam Long orderId, Principal principal) {String username = principal.getName(); // 当前登录用户Order order = orderService.findById(orderId);if (!order.getUsername().equals(username)) {throw new AccessDeniedException("无权访问该订单");}return order;
}
✅ 优点:简单直接,杜绝参数篡改。
⚠ 注意:不要直接信任前端传的 userId
。
2. 使用 Spring Security + 方法级权限控制
利用 @PreAuthorize
/ @PostAuthorize
注解做 权限 + 数据校验。
@PreAuthorize("@securityService.canAccessOrder(principal.username, #orderId)")
@GetMapping("/order/detail")
public Order getOrderDetail(@RequestParam Long orderId) {return orderService.findById(orderId);
}
SecurityService
:
@Service
public class SecurityService {public boolean canAccessOrder(String username, Long orderId) {Order order = orderMapper.findById(orderId);return order != null && order.getUsername().equals(username);}
}
✅ 优点:和权限体系无缝结合,复用性高。
⚠ 注意:权限校验逻辑要集中管理,避免散落到各处。
3. 数据层过滤(Query 加用户条件)
在 DAO 层/Repository 层,直接加上当前用户的条件,避免查到别人的数据。
@Select("SELECT * FROM orders WHERE id = #{orderId} AND username = #{username}")
Order findByIdAndUsername(@Param("orderId") Long orderId, @Param("username") String username);
✅ 优点:数据源头控制。
⚠ 注意:如果有批量查询,需要特别注意条件一致性。
4. 资源标识加密/混淆
代替暴露自增 ID,例如使用 UUID、雪花 ID、HashID 等。
即使 ID 被猜测,也不能轻易访问到资源。
String encryptedId = encrypt(orderId); // 例如AES加密
✅ 优点:增加枚举成本,降低暴力破解风险。
⚠ 注意:不是核心防御手段,必须配合权限校验。
5. 审计 & 监控
对敏感数据的访问做日志记录。
配合异常访问频率报警(防止批量爆破 ID)。
四、防御策略总结
方法 | 层级 | 适用场景 | 缺点 |
---|---|---|---|
后端资源归属校验 | 控制器层 | 所有敏感接口 | 需要每个接口写逻辑 |
Spring Security 方法权限 | 服务层 | 业务方法 | 学习曲线高 |
数据层过滤 | DAO层 | 查询数据接口 | 复杂查询不易统一处理 |
ID 加密/混淆 | 前后端 | 避免 ID 猜测 | 不是单独防御手段 |
审计与监控 | 全局 | 事后追踪 | 无法预防攻击 |