核心是将权限校验强制前置且服务端执行,分功能、数据、操作三层;所有接口须做资源归属校验,列表查询嵌入权限过滤;高危操作需上下文绑定与二次验证;网关层统一鉴权并对接权限中心实时校验。

核心是把权限校验从“可有可无”变成“强制前置”,且必须在服务端完成,不能依赖前端传来的任何标识。
权限模型必须分层落地
不能只靠一个“角色”字段做判断。要拆成三层:
-
功能权限:用户能访问哪些菜单、按钮、API路径(如
/api/order/list) - 数据权限:能查谁的数据(如仅限本部门订单、仅限本人创建的合同)
- 操作权限:对某条数据能做什么(如查看可导出,但编辑需二次验证)
例如:销售员调用/api/order/export,不仅要检查他有没有“导出”功能权限,还要确认他导出的订单属于其负责区域,并且该次导出请求已通过短信验证码授权。
所有接口必须做服务端资源归属校验
这是防水平越权最关键的一步。禁止直接使用前端传入的ID查询数据库。
- 危险写法:
orderService.findByOrderId(request.getParameter("orderId")) - 安全写法:
orderService.findByOrderIdAndOwner(orderId, currentUserId)或通过SQL加租户/归属条件:WHERE order_id = ? AND sales_rep_id = ?
对列表类接口,也需在查询语句中嵌入数据权限过滤逻辑,而不是查完再for循环过滤。
关键操作强制上下文绑定与二次验证
越权常发生在高危动作上,比如删除、审批、导出、资金划转。这类接口必须:
- 绑定当前会话的完整上下文:用户ID、设备指纹、IP段、时间窗口
- 对敏感操作单独设置操作令牌(OTP),有效期≤5分钟
- 支持人工审批流:如导出超1000条记录,自动转入待审队列,由主管确认后才执行
避免用“是否登录+是否有角色”就放行,而应判断“此刻这个用户,在这个设备、这个IP、这个业务场景下,是否真该执行这个动作”。
网关层统一鉴权 + 接口级细粒度拦截
权限控制不能散落在每个Controller里。应在API网关或统一拦截器中完成基础校验:
- 解析JWT/OAuth2 token,提取用户身份和角色
- 根据请求路径(如
POST /api/v1/user/{id}/reset-password)匹配预定义的权限策略 - 调用权限中心服务,传入用户ID、资源ID、操作类型(read/write/delete),实时返回是否允许
示例策略配置:{"path": "/api/tenant/*/data", "method": "GET", "abac": "user.tenantId == resource.tenantId && user.role in ['admin','viewer']"}

















