ABAC动态鉴权需结构化主体、资源、操作、环境四类属性,策略须独立存储支持热更新,拒绝默认,评估日志需审计,应嵌入控制器前通过注解或手动方式低侵入执行。

ABAC 动态鉴权不是配个中间件就能跑起来的模型,它依赖明确的属性结构、可执行的策略规则和运行时的实时评估逻辑。核心在于把“谁在什么条件下能做什么”翻译成可计算的表达式,并在每次请求中完成求值。
明确四类属性并结构化传入
ABAC 的决策基础是主体(subject)、资源(resource)、操作(action)和环境(environment)四类属性。不能只传用户对象或资源 ID,必须提前提取并组装成键值对数组或结构化对象。
- 主体属性:如 department=tech、role=manager、level=3,建议从用户模型 + 组织服务中聚合获取
- 资源属性:如 type=api、sensitivity=high、owner=john,需在路由或服务层解析目标资源元数据
- 操作属性:明确动作名,如 read、export、delete_draft,避免模糊动词(如 “manage”)
- 环境属性:如 time=09:45、ip=192.168.5.22、device=desktop,通常由请求上下文(Request/HttpContext)自动采集
设计可扩展的策略存储与加载方式
策略不能硬编码在 if-else 里,应独立存储、支持热更新。推荐用数据库 JSON 字段或专用策略表,字段至少包含:subject_match、resource_match、actions、effect(allow/deny)、condition(用于复杂表达式)。
- 简单策略可直接用键值匹配(如 subject.department == "finance"),适合高频访问场景
- 复杂策略建议存为表达式字符串(如 r.attr["sensitivity"] == "high" && env.time >= "09:00" && env.time ),配合 Symfony ExpressionLanguage 或 Casbin 的 eval() 安全执行
- 务必加缓存:用 Redis 或本地内存缓存策略集,设置 TTL(如 300 秒),避免每次请求查库
实现轻量但可靠的策略评估器
写一个无框架依赖的 AbacEvaluator 类,专注做一件事:输入四类属性,返回布尔结果。不要耦合 Auth 或 Gate 组件。
- 遍历策略时按优先级排序(如 ID 升序或 version 字段),第一条匹配即终止,避免覆盖误判
- matchPolicy() 方法应支持通配符(*)、集合包含(in)、范围比较(>=)、正则匹配(~)等基础运算
- 拒绝默认:未匹配任何策略时返回 false(deny),不依赖 fallback 角色或兜底权限
- 记录评估日志:记录 subject.id、resource.id、action、匹配策略 ID 和结果,便于审计与调试
嵌入业务入口,保持低侵入性
ABAC 鉴权应发生在控制器方法执行前,但不必侵入每个 action。推荐两种落地方式:
- 注解驱动:如 Java 的 @RequireAbac("order:export"),Spring AOP 提取属性并调用评估器
- 手动触发:在关键接口开头显式调用 $evaluator->evaluate('export', $userAttrs, $orderAttrs, $env),控制力更强,也更易单元测试
- 避免在模型层或 DAO 层做鉴权——属性可能尚未完整,且违反关注点分离

















