我有一个带有 2 个域控制器的域(my.local):
- 192.168.3.63 - DC1
- 192.168.3.64-DC2(主 DC)
我正在测试请求以查找用户是否是某个组的成员。这是一个查询过滤器:
(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))
如果我在两个控制器上都使用“Active Directory 用户和计算机”(ADUaC)管理单元,我会得到相同的结果:
但是当我运行 dsquery 时,没有得到任何结果:
C:\Users\admin>dsquery * domainroot -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
C:\Users\admin>
更有趣的是,如果我指定-s
参数,dsquery 会返回结果,但只有当我传递另一个 DC 时才会返回,而不是我运行 dsquery 的 DC
在 DC1 (192.168.3.63) 上: 注意根据 -s 开关的行为变化
C:\Users\admin>dsquery * domainroot -s 192.168.3.63 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
C:\Users\admin>
C:\Users\admin>dsquery * domainroot -s 192.168.3.64 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
"CN=adtest2,CN=Users,DC=my,DC=local"
C:\Users\admin>
在 DC2 (192.168.3.64) 上:
C:\Users\admin>dsquery * domainroot -s 192.168.3.63 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
"CN=adtest2,CN=Users,DC=my,DC=local"
C:\Users\admin>
C:\Users\admin>dsquery * domainroot -s 192.168.3.64 -filter "(&(&(objectClass=user)(sAMAccountName=adtest2))(memberOf:1.2.840.113556.1.4.1941:=CN=Test.NestedB,CN=Users,DC=my,DC=local))"
C:\Users\admin>
我尝试使用 和 - 运行 dsquery domainroot
,forestroot
但"DC=my,DC=local"
没有效果。我还尝试指定-scope subtree
,但这是默认设置。
- 为什么不指定 DC 的 dsquery 总是无法找到用户而 ADUaC 却总是成功?
- 为什么 dsquery 仅返回来自不同 DC 的结果,但是当指定 -s 开关时却返回来自当前 DC 的结果?
- 为了使 dsquery 持续工作,我可以/应该做哪些改变?
答案1
这不会是一个完整的答案,因为验证需要太长时间,而且我也不清楚具体细节,但我希望它与包含的具体查询有关1.2.840.113556.1.4.1941
。
这是LDAP_MATCHING_RULE_IN_CHAIN
OID,它特定于 Active Directory LDAP。如果您指定forestroot
,则您正在访问 GC。对于domainroot
,它显然是域根。我认为这里的问题是,这种方法不是通过递归遍历结构来搜索对象的传统方法。例如,如果您按名称进行匹配。
LDAP_MATCHING_RULE_IN_CHAIN
是一种特定于 AD 的“快捷方式”方法 - 有点像 SQL 中的存储过程。因此,要使用它,您需要绑定到在协议级别提供该特定功能的 LDAP 服务器 (DC)。就像能够查看数据库表很容易一样,但要使用存储过程,您需要使用 SQL 功能。
通过运行 LDP.exe 并绑定到 DC,您可以了解我的意思 - 当您执行绑定时,DC 将在 下列出它支持的 LDAP 功能SupportedControl
。有了这些,它们通常具有可以进一步查询的子控件,我认为LDAP_MATCHING_RULE_IN_CHAIN
可能是其中之一。
请记住,GUI 在后台为您做了很多工作。它给您的并不是纯粹的 LDAP - 它使用 DLL 和 .NET 钩子来检索数据并以友好的方式对其进行格式化。
因此,为了使您的查询更加一致,您需要绑定到特定的 DC 来访问LDAP_MATCHING_RULE_IN_CHAIN
协议方法,因为您不仅仅是“浏览”目录。我没有看到您使用开关的示例-d [domain DNS name]
。这将绑定到任何站点/域中的可用 DC。
dsquery user -name *test -d mydomain.org
最后,为了让你的生活很多更简单,使用这样的 LDAP 查询对于 DSQuery 来说实际上相当不寻常。它的重点是它应该是 LDAP 的一个友好(更)“包装器”,有点像 GUI。它有一些“助手”来使查询更容易和格式化数据。
如果您想要组 samAccountNames,获取用户所属组的通常方法如下。
dsquery user -samid %USERNAME% | dsget user -memberof | dsget group -samid
如果您只想要组 DN,则只需删除| dsget group -samid
。
这篇文章很好地介绍了该工具- 我建议您阅读它以获得关于常用语法和方法的良好提示。
这些天,我建议你开始掌握 AD Powershell。Powershell 确实更灵活,尽管 dsquery 仍然有一些技巧。