TL:DR; 扩展操作参数需要是按照BER标准编码的ASN.1值。这不是一项微不足道的任务,因此您可能需要一个额外的 npm 库,例如 asn1 来帮助完成此过程。
在梳理了 ldapjs 的代码,阅读了大量关于 ASN.1 以及 LDAP 如何使用 ASN.1 标准的内容后,经过一些试验和错误,我终于能够解决这个问题。由于明显缺乏这方面的文档,我想我会分享我在 stackoverflow 上学到的东西,这样其他人就不需要像我一样经历那么多麻烦。
一个工作示例
这使用 asn1 npm 库对发送的数据进行编码。
const { Ber } = require('asn1')
// ...
const CTX_SPECIFIC_CLASS = 0b10 << 6
const writer = new Ber.Writer()
writer.startSequence()
writer.writeString(dn,CTX_SPECIFIC_CLASS | 0) // sequence item number 0
// I'm choosing to omit the optional sequence item number 1
writer.writeString(newPassword,CTX_SPECIFIC_CLASS | 2) // sequence item number 2
writer.endSequence()
client.exop('1.3.6.1.4.1.4203.1.11.1',writer.buffer,(err,value,res) => {
// ...
})
什么是 ASN.1?
ASN.1 是一种用于描述对象接口的语言。这些接口的特殊之处在于它们与语言无关 - 即 javascript 可以创建一个符合这些接口之一的对象,对其进行编码,然后将其发送到 python 服务器,然后该服务器根据相同的接口解码和验证对象。 ASN.1 的大部分内容与我们试图完成的事情无关,但重要的是要注意我们试图做的是创建一个符合这些 ASN.1 接口之一的对象(LDAP 是围绕他们)。
什么是误码率?
BER 描述了一种表示符合 ASN.1 接口的对象的标准方法。使用 BER 标准,我们可以将 javascript 数据编码到 LDAP 服务器可以理解的缓冲区中。
BER 基础知识
BER 旨在成为一种非常紧凑的编码标准。我将在这里介绍基础知识,但如果您想了解有关 BER 二进制表示的更多详细信息(它是为 LDAP 用户量身定制的),我强烈推荐 this article。 A Layman's Guide to a Subset of ASN.1,BER,and DER 是另一个很好的资源。
ASN.1 描述了许多基本对象类型,例如字符串和数字,并且它描述了结构化对象类型,例如序列或集合。它还为用户提供了使用他们自己的自定义类型的能力。
在 BER 中,每条数据都以两个字节为前缀(通常):一个标识符字节和一个数据长度字节。标识符字节用有关它包含的数据类型的信息标记数据(字符串?序列?自定义类型?)。标签有四种“类别”:通用(例如字符串)、应用程序(LDAP 定义了一些您可能会遇到的应用程序标签)、特定于上下文(请参阅下面的“BER 序列”部分)和私有(不太可能适用)这里)。字符串标记的位序列将始终被解释为字符串标记,但自定义标记的位序列的含义可能因环境甚至在请求中而异。
在asn1 npm库中,可以写出一个字符串元素如下:
writer.writeString('text')
要查找所有可用函数,该库的作者要求您查看 the source code。
BER 序列
序列用于描述具有特定形状的对象(一组键值对)。某些元素可能是可选的,而其他元素是必需的。我所关注的 RFC 对其参数进行了以下描述。我们需要符合这个序列的接口,以便将我们的密码重置参数发送到 LDAP。
PasswdModifyRequestValue ::= SEQUENCE {
userIdentity [0] OCTET STRING OPTIONAL
oldPasswd [1] OCTET STRING OPTIONAL
newPasswd [2] OCTET STRING OPTIONAL }
[0]
、[1]
和 [2]
均指上下文特定的标签编号。使用上下文特定标记 1 标记的值将被解释为 oldPasswd 参数的值。我们不需要使用全局字符串标记来指示我们的值是字符串类型——LDAP 已经可以使用我们遵循的接口推断出该信息。这意味着在按此顺序写入字符串时,不是像之前那样做 writer.writeString('text')
(自动使用全局字符串标签),而是必须提供如下标签编号:
const CTX_SPECIFIC_CLASS = 0b10 << 6
writer.writeString(newPassword,CTX_SPECIFIC_CLASS | 2) // The second optional parameter allows you to set a custom tag on the data being set (instead of the default string tag).
标签字节的前两位保留用于指定标签类(在这种情况下,它是特定于上下文的类,或位“10”)。因此,CTX_SPECIFIC_CLASS | 2
指的是 RFC 描述的 newPasswd 序列项。请注意,如果我想省略一个可选的序列条目,我只是不写出用该序列 ID 标记的值。
结束语
希望这应该为读者提供足够的信息,以便能够为扩展的 LDAP 操作格式化和发送 BER 编码的参数。我想指出的是,我不是 ASN.1/BER 专家 - 以上所有信息只是我在过去几天自己的研究中理解这些概念的方式。所以,这篇文章中可能有一些错误解释的地方。如果您碰巧比我更了解这个主题,请随时编辑它。
本文链接:https://www.f2er.com/1095971.html