如何使用Novell.Directory.Ldap.NETStandard查询LDAP用户所属用户组
Novell.Directory.Ldap.NETStandard 查询AD用户所属组实现方案
方案1:读取用户memberOf属性(查询直接所属组)
该方案实现简单,适合不需要统计嵌套组的场景,仅需调整原有搜索参数,指定返回memberOf属性即可,修改后代码如下:
use connection = new LdapConnection() connection.Connect(credentials.host, LdapConnection.DefaultPort) connection.Bind($"{credentials.domain}\\{credentials.username}", credentials.password) match connection.Connected with | true -> // 提取域根DN作为搜索根路径 let domainDn = connection.GetSchemaDn().Split(',').Skip(1) |> String.concat "," // 匹配指定SAM账号的用户过滤器 let userFilter = $"(SAMAccountName={credentials.username})" // 指定返回属性,加入memberOf获取用户直接所属组 let returnAttrs = [|"samAccountName";"displayName";"memberOf"|] // 搜索范围设置为ScopeSub遍历整个域下的对象 let searchResults = connection.Search(domainDn, LdapConnection.ScopeSub, userFilter, returnAttrs, false) // 提取所有组DN let userDirectGroups = [ while searchResults.hasMore() do let userEntry = searchResults.next() let memberOfAttr = userEntry.getAttribute("memberOf") if memberOfAttr <> null then yield! memberOfAttr.StringValues ] return (Some userDirectGroups, String.Empty) | false -> return (None, $"Cannot connect to domain {credentials.domain} with user {credentials.username}")
方案2:递归查询所有所属组(含嵌套组)
如果需要查询用户所有所属组,包括用户所在组的父组等嵌套关系,可以使用AD专属的LDAP扩展匹配规则1.2.840.113556.1.4.1941实现,示例代码如下:
use connection = new LdapConnection() connection.Connect(credentials.host, LdapConnection.DefaultPort) connection.Bind($"{credentials.domain}\\{credentials.username}", credentials.password) match connection.Connected with | true -> let domainDn = connection.GetSchemaDn().Split(',').Skip(1) |> String.concat "," let userFilter = $"(SAMAccountName={credentials.username})" let userReturnAttrs = [|"distinguishedName"|] let userSearchResults = connection.Search(domainDn, LdapConnection.ScopeSub, userFilter, userReturnAttrs, false) if userSearchResults.hasMore() then let userDn = userSearchResults.next().DN // 递归匹配所有包含该用户的组 let nestedGroupFilter = $"(& (objectCategory=group) (member:1.2.840.113556.1.4.1941:={userDn}))" let groupReturnAttrs = [|"name";"distinguishedName"|] let groupSearchResults = connection.Search(domainDn, LdapConnection.ScopeSub, nestedGroupFilter, groupReturnAttrs, false) let allUserGroups = [ while groupSearchResults.hasMore() do let groupEntry = groupSearchResults.next() yield groupEntry.getAttribute("name").StringValue ] return (Some allUserGroups, String.Empty) else return (None, "User not found") | false -> return (None, $"Cannot connect to domain {credentials.domain} with user {credentials.username}")
注意事项
- 绑定的账号需要拥有对应域的用户、组查询权限,否则会返回空结果
- 多域林环境下需要连接全局编录服务器(端口3268)实现跨域组查询
memberOf属性默认不包含用户主组(如Domain Users),如果需要获取主组,可额外查询用户的primaryGroupID属性,匹配对应组的primaryGroupToken属性即可
内容的提问来源于stack exchange,提问作者Wojciech Szabowicz
相关产品推荐
相关产品推荐

