Spring Boot / Spring LDAP获取用户成员列表

我想通过从如下结构的LDAP存储库查询其ID来获取用户属性的列表

dn: uid=E000001 ,ou=People,o=Company,o=Internal cn: BOB DOLE statusid: active memberof: cn=foo_group, cn=Foos, ou=Groups, o=Company,o=Internal memberof: cn=bar_group, cn=Foos, ou=Groups, o=Company,o=Internal dn: uid=E000002 ,ou=People,o=Company,o=Internal cn: MARK TEST statusid: active memberof: cn=foo_group, cn=Foos, ou=Groups, o=Company,o=Internal memberof: cn=bar_group, cn=Foos, ou=Groups, o=Company,o=Internal 

例如,我查询用户ID“E00001”。 我想要归还这个

 ["cn=foo_group, cn=Foos, ou=Groups, o=Company,o=Internal", "cn=bar_group, cn=Foos, ou=Groups, o=Company,o=Internal" 

以下是检索用户组的多种方法:

  • 如果您有一个没有嵌套组的简单LDAP服务器,memberOf通常就足够了:

     String userCN = "user1"; //Get the attribute of user's "memberOf" ArrayList membersOf = ldapTemplate.search( query().where("sAMAccountName").is(userCN), (AttributesMapper>) attrs -> Collections.list(attrs.get("memberOf").getAll()) ).get(0); 
  • 但是如果你有嵌套组,事情会变得更复杂:

     /* * Get user distinguised name, example: "user" -> "CN=User Name,OU=Groups,OU=Domain Users,DC=company,DC=something,DC=org" * This will be used for our query later */ String distinguishedName = ldapTemplate.search( query().where("sAMAccountName").is(userCN), (AttributesMapper) attrs -> attrs.get("distinguishedName").get().toString() ).get(0); //.get(0): we assume that search will return a result /* * This one recursively search for all (nested) group that this user belongs to * "member:1.2.840.113556.1.4.1941:" is a magic attribute, Reference: * https://msdn.microsoft.com/en-us/library/aa746475(v=vs.85).aspx * However, this filter is usually slow in case your ad directory is large. */ List allGroups = ldapTemplate.search( query().searchScope(SearchScope.SUBTREE) .where("member:1.2.840.113556.1.4.1941:").is(distinguishedName), (AttributesMapper) attrs -> attrs.get("cn").get().toString() ); 

对于googlers:请注意,这与org.springframework.boot:spring-boot-starter-data-ldap ,如果有人需要Bean初始化代码:

 @Component @EnableConfigurationProperties public class Ldap { @Bean @ConfigurationProperties(prefix="ldap.contextSource") public LdapContextSource contextSource() { return new LdapContextSource(); } @Bean public LdapTemplate ldapTemplate(ContextSource contextSource) { return new LdapTemplate(contextSource); } } 

使用application.yml中的以下配置模板:

 ldap: contextSource: url: ldap://your-ldap.server base: dc=Company,dc=Domain,dc=Controller userDn: username password: hunter2 #you'll want connection polling set to true so ldapTemplate reuse the connection when searching recursively pooled: true 

当魔术数字的表现不好时:如果你的ldap目录很大,那么使用幻数的最后一个实际上很慢,在这种情况下,递归搜索ldap更快。 这是一个帮助类,可以详尽地搜索用户所属的所有组:

 public class LdapSearchRecursive { private final LdapTemplate ldapTemplate; private Set groups; public LdapSearchRecursive(LdapTemplate ldapTemplate) { this.ldapTemplate = ldapTemplate; this.groups = new HashSet<>(); } /** * Retrieve all groups that this user belongs to. */ public Set getAllGroupsForUserRecursively(String userCN) { List distinguishedNames = this.ldapTemplate.search( query().where("objectCategory").is("user").and( query().where("sAMAccountName").is(userCN) .or(query().where("userPrincipalName").is(userCN)) ), (AttributesMapper) attrs -> attrs.get("distinguishedName").get().toString() ); if (distinguishedNames.isEmpty()) { throw new UsernameNotFoundException("User not recognized in LDAP"); } return this.getAllGroupsRecursivelyByUserDistinguishedName(distinguishedNames.get(0), null); } private Set getAllGroupsRecursivelyByUserDistinguishedName(String dn, @Nullable String parentDN) { List results = this.ldapTemplate.search( query().where("member").is(dn), (AttributesMapper) attrs -> attrs.get("distinguishedName").get().toString() ); for (String result : results) { if (!(result.equals(parentDN) //circular, ignore || this.groups.contains(result) //duplicate, ignore )) { this.getAllGroupsRecursivelyByUserDistinguishedName(result, dn); } } this.groups.addAll(results); return this.groups; } }