java Spring Boot / Spring LDAP 获取用户的成员列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45546775/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring Boot / Spring LDAP Get List of memberof for a User
提问by excedion
I want to get a list of a users attributes by querying on their ID from an LDAP repository structured like below
我想通过从如下结构的 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
So for example I query on the user id "E00001". I want to return this
例如,我查询用户 ID“E00001”。我想退货
["cn=foo_group, cn=Foos, ou=Groups, o=Company,o=Internal", "cn=bar_group, cn=Foos, ou=Groups, o=Company,o=Internal"
回答by EwyynTomato
Here's multiple ways to retrieve user groups:
以下是检索用户组的多种方法:
In case that you have a simple LDAP server with no nested groups, memberOf is usually enough:
String userCN = "user1"; //Get the attribute of user's "memberOf" ArrayList<?> membersOf = ldapTemplate.search( query().where("sAMAccountName").is(userCN), (AttributesMapper<ArrayList<?>>) attrs -> Collections.list(attrs.get("memberOf").getAll()) ).get(0);
But in case you have nested groups, things become more complicated:
/* * 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<String>) 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<String> allGroups = ldapTemplate.search( query().searchScope(SearchScope.SUBTREE) .where("member:1.2.840.113556.1.4.1941:").is(distinguishedName), (AttributesMapper<String>) attrs -> attrs.get("cn").get().toString() );
如果您有一个没有嵌套组的简单 LDAP 服务器,memberOf 通常就足够了:
String userCN = "user1"; //Get the attribute of user's "memberOf" ArrayList<?> membersOf = ldapTemplate.search( query().where("sAMAccountName").is(userCN), (AttributesMapper<ArrayList<?>>) 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<String>) 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<String> allGroups = ldapTemplate.search( query().searchScope(SearchScope.SUBTREE) .where("member:1.2.840.113556.1.4.1941:").is(distinguishedName), (AttributesMapper<String>) attrs -> attrs.get("cn").get().toString() );
For googlers:note that this has dependency of org.springframework.boot:spring-boot-starter-data-ldap
, and in case someone needs the Bean initialization code:
对于 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);
}
}
with the following config template in application.yml:
使用 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
For when magic number's performance is bad:The last one using magic number is actually quite slow if your ldap directory is large, and searching ldap recursively is faster in this case. Here's a helper class to exhaustively search all groups that a user belongs to:
当幻数的性能很差时:如果你的 ldap 目录很大,最后一个使用幻数实际上很慢,在这种情况下递归搜索 ldap 会更快。这是一个帮助类,用于彻底搜索用户所属的所有组:
public class LdapSearchRecursive {
private final LdapTemplate ldapTemplate;
private Set<String> groups;
public LdapSearchRecursive(LdapTemplate ldapTemplate) {
this.ldapTemplate = ldapTemplate;
this.groups = new HashSet<>();
}
/**
* Retrieve all groups that this user belongs to.
*/
public Set<String> getAllGroupsForUserRecursively(String userCN) {
List<String> distinguishedNames = this.ldapTemplate.search(
query().where("objectCategory").is("user").and(
query().where("sAMAccountName").is(userCN)
.or(query().where("userPrincipalName").is(userCN))
),
(AttributesMapper<String>) 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<String> getAllGroupsRecursivelyByUserDistinguishedName(String dn, @Nullable String parentDN) {
List<String> results = this.ldapTemplate.search(
query().where("member").is(dn),
(AttributesMapper<String>) 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;
}
}