输出控制策略的基本原理:策略决策点与策略执行点

聊到输出控制策略,很多新手第一反应就是「加个if判断不就行了?」。

嗯,如果只是判断权限,确实一个if搞定。但实际生产环境里,策略可能要跨服务、跨节点、甚至跨组织生效。这时候,你需要明白两个核心角色——策略决策点(PDP)和策略执行点(PEP)。

说白了,一个负责「想」,一个负责「做」。

为什么要把决策和执行分开?

我个人习惯把系统里的职责切得越细越好。比如一个场景:多个SDK实例都要校验同一份策略。如果每个实例自己判断逻辑,策略一变,你得挨个升级SDK版本——想想就头疼。

我在项目里遇到过这种情况。业务方突然要求「所有用户的手机号输出都要脱敏」。如果你把判断逻辑散落在各个终端,改起来至少一星期。但如果用了PDP/PEP分离的架构,只需要在下发策略的PDP里改一条规则,所有PEP自动生效。

这就是分离的好处——控制面与数据面解耦。

核心结论:

  • PDP:只做决策,不接触实际数据
  • PEP:只做执行,不修改策略逻辑
  • 两者通过标准协议通信(比如XACML、自定义JSON)

策略决策点(PDP)的职责

PDP,你可以把它想象成一个「策略大脑」。

它接收PEP发来的请求描述(谁、要什么、在什么环境下),然后查策略库、算权限、最终吐出一个决定——通常是Permit(允许)或Deny(拒绝)。

举个例子:

// PEP向PDP发起的请求描述(简化版)
{
    "subject": "用户A",
    "resource": "用户B的手机号",
    "action": "读取",
    "environment": {
        "time": "2024-03-15 14:30:00",
        "from_ip": "192.168.1.10"
    }
}

PDP收到后,对比策略库里的规则:

  • 规则1:用户A 无权读取用户B的手机号 → 匹配 → Deny
  • 规则2:如果time在09:00-18:00内,且from_ip在内网,允许 → 环境因子匹配但不满足主体/资源
  • 最终结果:Deny

为什么PDP要做这么复杂?

你想想看,如果PDP只做「有无权限」的简单判断,那和写死if没啥区别。真正的隐私共享场景里,策略往往带上下文——时间、地点、数据用途、数据量级。PDP的任务就是把这些因素综合起来,算出最精细的结果。

策略执行点(PEP)的职责

PEP是执行者,也是「最后一道防线」。

它拦截所有数据输出请求,把请求描述发给PDP,然后严格按照PDP的返回值来放行或拒绝。你可能会问:「如果PDP返回了Permit,PEP就直接放行吗?」

不一定。

我在项目中遇到过一种坑——PDP返回了Permit,但PEP发现当前数据已经被标记为高风险。这时候PEP应该有「自我保护」能力,阻止输出并上报异常。

经验建议:PEP永远不要完全信任PDP。即使PDP说允许,PEP也要做一次快速的基本校验——数据大小是否异常、输出频率是否超限。这叫「纵深防御」。

PDP与PEP的典型交互流程

一张图就能讲清楚。咱们来看下面的SVG流程图:

PDP与PEP交互流程图 PEP端(数据面) PDP端(控制面) 1. 用户发起数据输出请求 打包请求描述 2. 发送请求到PDP 3. 查策略库,计算决策 匹配规则、环境因子 4. 返回 Permit / Deny 5. 按决策执行(放行/拒绝) 6. 将结果返回给用户 关键机制 PEP不参与决策逻辑 PDP不接触原始数据

从图上你能看到,PEP和PDP之间是异步分离的。PEP只负责收请求、发请求、收结果、执行。PDP只负责算决策、返回决策。两者之间没有任何数据依赖。

PDP与PEP的职责对比

我整理了一个对比表,方便你快速记忆:

维度 PDP(策略决策点) PEP(策略执行点)
核心能力 策略解析 + 环境因子计算 + 规则匹配 请求拦截 + 结果执行 + 基本安全校验
数据接触 不接触原始数据,只处理元数据 接触原始数据,但只做执行
部署位置 中心化策略服务 SDK内部、网关、服务代理
通信协议 接收标准请求,输出标准响应 发送请求,接收决策
失败处理 超时时返回 Deny(安全模式) 超时时拒绝输出并上报

避坑指南:

我曾经在一个项目里把PDP的决策逻辑写得太复杂——一次性计算30多个环境因子,结果PDP响应时间涨到了200ms。PEP等不起,直接超时报了Deny,业务方说「你们的SDK有问题,啥都输出不了」。后来我做了两件事:把高频决策因子缓存到PEP本地;PDP只算变化较慢的全局策略。一下子解决问题。

教训:PDP不要做太重,PEP不要等太久。

完整流程回顾

咱们用个场景把整个链路串一遍:

  1. 用户通过SDK请求输出「用户B的定位信息」
  2. PEP拦截请求,生成描述:{subject: 用户A, resource: 用户B定位, action: 读取, env: {时间, IP}}
  3. PEP将描述发给PDP
  4. PDP查到策略:「用户A在非工作时间不可读取他人定位」 → 当前时间22:00 → Deny
  5. PDP返回Deny给PEP
  6. PEP执行拒绝,给用户返回「权限不足」

这个流程里,PDP和PEP各司其职。哪怕后续策略变成「允许读取,但必须脱敏到街道级别」,也只需要修改PDP的规则,PEP不用改一行代码。

一点个人小心得:刚开始设计SDK时,我总想把PDP和PEP写在一坨代码里。后来发现每次升级都得全量发版。拆开后,PDP可以单独灰度发布,PEP也可以独立更新安全校验逻辑。你想想看,这对于一个隐私共享SDK来说,维护成本直接降了一个量级。

小结

策略决策点与策略执行点,本质上是控制与执行分离的设计模式。

  • PDP要精——专注于策略计算,别被业务细节拖慢
  • PEP要稳——牢牢守住数据输出的大门,不给非法请求任何机会

记住这个原则,不管后面面对多复杂的策略规则,你的SDK架构都会清晰得多。