[英]Unable to get modification context for Active Directory records through Spring LDAP
I am trying to use Spring LDAP to retrieve and modify user information in an Active Directory server, but I can't retrieve a user record by dn so that I can modify it.我正在尝试使用 Spring LDAP 来检索和修改 Active Directory 服务器中的用户信息,但我无法通过 dn 检索用户记录以便我可以修改它。
I am able to find the record by username with the LdapTemplate.search
method.我可以使用
LdapTemplate.search
方法按用户名查找记录。 There is no dn
attribute in the record, but distinguishedName
looks like it should be correct.记录中没有
dn
属性,但是distinguishedName
看起来应该是正确的。 When I use LdapTemplate.lookupContext
to retrieve the record by dn, however, the server says that it can't find the record by the dn
that it just gave me.但是,当我使用
LdapTemplate.lookupContext
按 dn 检索记录时,服务器说它找不到它刚刚给我的dn
记录。 What am I doing wrong?我究竟做错了什么?
It seem wrong that the LdapTemplate
search method doesn't give you a handle that you can use without doing a second query from the Active Directory. LdapTemplate
搜索方法没有为您提供无需从 Active Directory 进行第二次查询即可使用的句柄,这似乎是错误的。 Is there a better way to do this?有一个更好的方法吗?
I have created a sample Groovy application to demonstrate the problem.我创建了一个示例 Groovy 应用程序来演示该问题。 My Spring Boot application creates this class and then invokes the runTest method.
我的 Spring 引导应用程序创建此 class 然后调用 runTest 方法。
package edu.sunyjcc.gateway.ldap;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.ldap.LdapName;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import static org.springframework.ldap.query.LdapQueryBuilder.query;
import org.springframework.ldap.core.DirContextOperations;
public class ActiveDirectoryDNSample {
LdapTemplate ldapTemplate;
/** Attributes to fetch from server */
static attributeList = [
"sAMAccountName",
"distinguishedName",
"baseDn",
"userPrincipalName",
];
/** This will represent the record retrieved from Active Directory */
class Person {
/** Raw data from server */
Map attributes = [:];
/** Return the distinguished name */
String getDn() {
attributes?.distinguishedName;
}
String getUsername() {
attributes?.sAMAccountName;
}
String toString() {
"${this.username} <${this.getDn()}>"
}
/** Get a handle to the object from AD so we can modify it. This fails. */
def getContext() {
assert ldapTemplate;
println "in getContext()";
def dn = new LdapName(this.getDn());
println "...dn=$dn"
assert dn;
// The next line throws an exception.
DirContextOperations context = ldapTemplate.lookupContext(dn);
println "...context=$context"
}
}
/** Convert the attributes from AD into a Person object */
class RecordMapper implements AttributesMapper<Person> {
/** Create a Person object from the attribute map */
Person mapFromAttributes(Attributes attributes)
throws NamingException {
assert ldapTemplate;
Person prec = new Person(
ldapTemplate: ldapTemplate
);
attributeList.collect {
[attrName: it, attr: attributes.get(it)]
}.grep {it.attr}.each {
prec.attributes."${it.attrName}" = it.attr.get() as String;
}
return prec;
}
}
/** Get a user from Active Directory */
public List<Person> getByUsername(String username) throws Exception {
assert ldapTemplate;
AttributesMapper attrMapper = new RecordMapper();
assert attrMapper;
List s = ldapTemplate.search(
query().
where("sAMAccountName").is(username),
attrMapper
);
if (s == null) {
System.err.println("s is null");
}
return s?:[];
}
/** Try to fetch a record and get a modify context for it */
public runTest(String username) {
println "In ActiveDirectoryDNSample.runText($username)"
assert ldapTemplate;
def records = getByUsername(username);
println "Retrieved ${records?.size()} records";
records.each {println " $it"}
println "Now try to get the context for the records"
records.each {
person ->
println " getting context for $person";
def context = person.getContext();
println " context=$context"
}
}
public ActiveDirectoryDNSample(LdapTemplate ldapTemplate ) {
this.ldapTemplate = ldapTemplate;
}
}
In ActiveDirectoryDNSample.runText(testuser)
Retrieved 1 records
testuser <CN=Test User,CN=Users,DC=jccadmin,DC=sunyjcc,DC=edu>
Now try to get the context for the records
getting context for testuser <CN=Test User,CN=Users,DC=jccadmin,DC=sunyjcc,DC=edu>
in getContext()
...dn=CN=Test User,CN=Users,DC=jccadmin,DC=sunyjcc,DC=edu
and then it dies with a javax.naming.NameNotFoundException
with the following data.然后它死于带有以下数据的
javax.naming.NameNotFoundException
。
[LDAP: error code 32 - 0000208D: NameErr: DSID-03100238, problem 2001 (NO_OBJECT), data 0, best match of:
'CN=Users,DC=jccadmin,DC=sunyjcc,DC=edu'
\0]
Thanks for any help you can give me.感谢你给与我的帮助。
It turns out that there was, indeed, a better way.事实证明,确实有更好的方法。 Instead of using an
org.springframework.ldap.core.AttributesMapper
in the search, you use org.springframework.ldap.core.ContextMapper
.代替在搜索中使用
org.springframework.ldap.core.AttributesMapper
,您使用org.springframework.ldap.core.ContextMapper
。
In my example, I added a field to the Person class, which will hold a reference to the context.在我的示例中,我向 Person class 添加了一个字段,该字段将包含对上下文的引用。
DirContextOperations context;
Then I created a new class extending org.springframework.ldap.core.support.AbstractContextMapper
.然后我创建了一个新的 class 扩展
org.springframework.ldap.core.support.AbstractContextMapper
。
class PersonContextMapper extends AbstractContextMapper {
@Override
protected Object doMapFromContext(DirContextOperations ctx) {
AttributesMapper attrMapper = new RecordMapper();
Person p = attrMapper.mapFromAttributes(ctx.attributes);
p.context = ctx;
return p;
}
}
When I passed it to the ldapTemplate.search
method in the place of the AttributeMapper
, I was able to use the context to update the Active Directory.当我将它传递给
ldapTemplate.search
方法来代替AttributeMapper
时,我能够使用上下文来更新 Active Directory。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.