摘要
- 早期 LDAP 只要求
MessageID在同一会话尚未结束的请求中不重复。一次搜索返回的条目、引用和最终结果都回显这个编号,所以多项操作可以在一条连接上交错。 - Abandon 暴露了编号的边界:取消请求自己的信封有一个 ID,负载里另一个 ID 指向目标;但 Abandon 本身和成功被放弃的搜索都没有完成回应。需要结果时,RFC 3909 另行定义了 Cancel。
- 分页搜索每取一页都换用新的 message ID,真正延续结果集的是服务器给出的不透明 cookie。编号不是身份凭证、长期查询名,也不证明更新已回滚。
搜索从来不是一问一答
LDAP 的“轻量”是相对于 X.500 目录访问成本而言,并不意味着每项操作只有一条回应。客户端查询一个子树时,服务器可能返回零个、几十个或几千个条目,还可能返回尚未探索区域的引用,最后才给出成功或错误。
1993 年 7 月发布的 RFC 1487 把所有协议操作装进同一种 LDAPMessage 信封。当时唯一的公共字段就是 messageID。它必须区别于同一 LDAP 会话里其他未完成请求的编号,服务器则在属于该请求的每个回应信封中回显原值。
因此,这个整数标识的是一项正在进行的操作,不是一只网络包。若搜索返回的每个条目都换号,客户端反而无法知道哪些条目和哪一个终止结果组成同一条结果流。目录对象由 distinguished name 命名,操作含义由 protocolOp 类型说明;MessageID 只负责把收到的报文接回正确的本地状态。
这个设计也没有追求全球唯一。另一个连接完全可以同时使用 41;同一客户端在旧操作确实结束后也可以再用 41。比较范围从一开始就是“本会话、仍在处理的操作”。
异步交换让编号真正有用
1995 年的 RFC 1777 明确说,客户端和服务器都不必同步工作,多项操作的请求与回应可以按任意顺序交换。一个宽泛搜索尚在返回条目时,客户端可以发起快速 compare;服务器也可以先完成 compare。
线上顺序可能是:搜索 41、比较 42、条目 41、比较结果 42、另一个条目 41、搜索终止 41。TCP 保证字节可靠有序,却不负责解释哪段已编码消息属于哪项应用操作。这个分流工作由 MessageID 完成。
1997 年的 RFC 2251 把机制带入 LDAPv3,把最大值限定为 2^31−1,说明客户端通常递增计数器,并禁止在收到旧请求最终回应前复用编号。搜索回应也被分得更清楚:SearchResultEntry 与 SearchResultReference 可以交错,最后一个 SearchResultDone 才说明搜索成功或失败。
最终回应于是同时提供两类证据。result code 描述操作结局;它的到达又通常证明服务器不再需要这个操作编号。收到第一个条目绝不等于搜索成功,收到最后一个字节也不能只凭网络安静来判断完成。
零被留给没有问题的发言
2006 年,LDAPv3 规格重新整理。RFC 4510 记录了新旧文件的关系,RFC 4511 给出修订后的协议规则。
请求的 messageID 从此明确必须非零;零保留给服务器主动发出的 unsolicited notification。例如 Notice of Disconnection 并不是对客户端某项操作的回应,它用零号信封和通知自己的对象标识符表达含义。
这不是中央机构分配的编号空间,而是接收端可以立即执行的划界:正整数用于客户端发起、仍可相关联的工作;零用于规格允许的服务器主动通知。编号本身仍不说明通知为什么可信,也不说明操作是否获准。
编号何时可复用,取决于服务器是否还在服务旧请求,而不是经过了多少秒。收到最终回应是常见证据;随后完成一次 Bind 也可能建立新的确定边界。超时可以促使客户端关闭连接或启动核对,但沉默不会自动清空另一端的状态表。
Abandon 同时用了两个编号,却没有结局回执
Abandon 是理解这条边界的最好入口。取消动作本身也是 LDAP 请求,因此外层信封有一个新的 MessageID;它的负载又是一个 MessageID,指向客户端希望停止的旧操作。前者让取消动作可被本地追踪,后者选择目标。
Abandon 没有回应。依 RFC 4511,服务器“可以”放弃目标。如果目标是正在发送条目的搜索,服务器必须停止继续发条目,而且不得发送 SearchResultDone。但已经在途的结果仍可能到达,有些操作也可能根本不能被放弃。
这使沉默保持了诚实的歧义。客户端只是在说“不再需要这个结果”,协议没有假装它获得了执行证明。目标编号可以完全正确,服务器行为仍可能无法从线上确认。
RFC 2251 因而规定,在较后发出的另一请求收到回应之前,不要复用 Abandon 自己或目标操作的 ID。那个较后回应并不是取消确认,只能证明连接上的处理已经向前推进,降低立即混号的风险。
Cancel 给出了结果,而没有偷偷增强旧信号
如果应用必须知道取消结果,2004 年的 RFC 3909 提供了新的 Cancel extended operation。它没有修改 Abandon 的意义,而是另建一条有回应的路径。
Cancel 信封有自己的 MessageID,负载中的 cancelID 指向待取消操作。成功时,服务器回应 Cancel 成功,同时让目标操作以 canceled 结果结束;失败则区分服务器不认识该操作、该操作不能取消,或请求已经太迟。
“太迟”这一结果尤其关键。RFC 3909 举的例子,是目录更新已经提交到底层数据存储。即使 cancelID 精确选中了正确操作,也不会因此产生回滚能力。相关性证明和效果逆转从来不是一回事。
Bind、StartTLS、Unbind、Abandon 与 Cancel 自己不能成为 Cancel 的目标。这些动作建立、改变或拆除普通操作编号赖以成立的认证、安全与会话语境。若允许普通编号任意抹去这些边界,相关键就会被赋予本来没有的控制权。
下一页必须换号
分页把 MessageID 的狭窄职责展示得最清楚。RFC 2696 让服务器在 SearchResultDone 中给出一个不透明 cookie。客户端索取下一页时,要重复搜索条件,却必须换用新的 messageID,并带上最后收到的 cookie;页大小可以调整。
每一页请求都是新的 LDAP 操作。跨操作保存结果位置的是 cookie,不是上一页编号。旧 cookie 未必还能使用,空 cookie 表示序列结束。Abandon 可以停止当前某页,但可能使 cookie 失效;要结束整个分页序列,客户端以最后 cookie 和页大小零再发一项搜索。
这样,三个容易混淆的问题被拆开:Message ID 回答“本会话哪项在途工作产生了这条消息”;cookie 回答“后续操作可从服务器哪种状态继续”;distinguished name 才说明“目录里的对象是谁”。
史料证明规则,不证明今天的产品
本文的封闭证据集是 RFC 1487、RFC 1777、RFC 2251、RFC 2696、RFC 3909、RFC 4510 与 RFC 4511。它们能证明格式、规范边界和修订历史,不能证明某种实现已经合规,也不能证明一段抓包中操作的真实结局。
这个小整数能够长期存在,正因为它没有索取过多权力。接收方能在本地检查的,只是消息与在途状态的关联。完成、取消、延续、认证和授权,都需要各自独立的证据。
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
