【问题标题】:Unable to get modification context for Active Directory records through Spring LDAP无法通过 Spring LDAP 获取 Active Directory 记录的修改上下文
【发布时间】:2021-05-13 04:50:38
【问题描述】:

我正在尝试使用 Spring LDAP 来检索和修改 Active Directory 服务器中的用户信息,但我无法通过 dn 检索用户记录以便我可以修改它。

我可以使用LdapTemplate.search 方法通过用户名找到记录。记录中没有dn 属性,但distinguishedName 看起来应该是正确的。但是,当我使用LdapTemplate.lookupContext 通过dn 检索记录时,服务器说它找不到它刚刚给我的dn 记录。我做错了什么?

LdapTemplate 搜索方法没有为您提供无需从 Active Directory 进行第二次查询即可使用的句柄,这似乎是错误的。有没有更好的方法来做到这一点?

我创建了一个示例 Groovy 应用程序来演示该问题。我的 Spring Boot 应用程序创建这个类,然后调用 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

然后它会以 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]

感谢您能给我的任何帮助。

【问题讨论】:

    标签: spring active-directory spring-ldap


    【解决方案1】:

    事实证明,确实有更好的方法。在搜索中不要使用org.springframework.ldap.core.AttributesMapper,而是使用org.springframework.ldap.core.ContextMapper

    在我的示例中,我向 Person 类添加了一个字段,该字段将保存对上下文的引用。

    DirContextOperations context;
    

    然后我创建了一个扩展 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;
      }
    }
    

    当我将它传递给 ldapTemplate.search 方法来代替 AttributeMapper 时,我能够使用上下文来更新 Active Directory。

    【讨论】:

      猜你喜欢
      • 2015-09-11
      • 1970-01-01
      • 2019-05-18
      • 2014-12-01
      • 2019-08-29
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多