从Spring连接LDAP

时间:2013-01-05 14:13:16

标签: spring ldap jndi

我必须实现基于Spring的Web应用程序,允许用户管理LDAP数据。与LDAP的连接只能使用JNDI框架(不允许SpringLDAP)。

为此,我实现了一个实用程序类来执行基本操作(添加,更新,删除,列表,...)。

以下是此类的一小段代码:

public class LdapUtility {


    private static LdapUtility instance;

    private DirContext dirContext;


    public static LdapUtility getInstance() {

        if(LdapUtility.instance == null)
            LdapUtility.instance = new LdapUtility();

        return LdapUtility.instance;
    }

    /**
     * Connect to the LDAP
     */
    private LdapUtility() {

        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, "ldap://localhost:389");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "cn=Manager,dc=my-domain,dc=com");
        env.put(Context.SECURITY_CREDENTIALS, "secret");

        try {
            dirContext = new InitialDirContext(env);
        }
        catch(Exception ex) {
            dirContext = null;
        }
    }

    public void addUser(User u) {

           dirContext.createSubcontext(....); //add user in the LDAP
    }
}

使用此代码,我可以通过调用LdapUtility.getInstance()...来访问我的所有方法,但是不会释放与LDAP的连接。

另一种方法是在每次操作之前连接到LDAP,但在这种情况下,与LDAP的连接太多了......

所以,这是我的问题:访问这些方法的最优雅/最智能的方法是什么?

提前谢谢: - )

4 个答案:

答案 0 :(得分:1)

由于您已经在使用Spring,我建议您使用Spring LDAP

  

Spring LDAP是一个Java库,用于根据Spring的JdbcTemplate模式简化LDAP操作。该框架减轻了用户的常见杂务,例如查找和关闭上下文,循环结果,编码/解码值和过滤器等等。

特别是如果您不熟悉LDAP和潜在的性能问题,它可以帮助您开始使用这样的实用程序库,它将为您完成所有繁重的任务。

您可以在spring config中配置LDAP连接设置:

<bean id="contextSource" class="org.springframework.ldap.core.support.LdapContextSource">
  <property name="url" value="ldap://localhost:389" />
  <property name="base" value="dc=example,dc=com" />
  <property name="userDn" value="cn=Manager" />
  <property name="password" value="secret" />
</bean>

<bean id="ldapTemplate" class="org.springframework.ldap.core.LdapTemplate">
  <constructor-arg ref="contextSource" />
</bean>

然后,您可以在需要执行LDAP操作的地方使用LdapTemplate

return ldapTemplate.search(
     "", "(objectclass=person)",
     new AttributesMapper() {
        public Object mapFromAttributes(Attributes attrs)
           throws NamingException {
           return attrs.get("cn").get();
        }
     });

答案 1 :(得分:0)

有几种方法可以连接到ldap。使用javax.naming。*就是其中之一。在javadoc中,您可能会发现,SPI提供程序中的类管理它们自己的连接,因此您不关心它 - 这可能是您的问题的答案 - 请参阅JDK doc以及Context如何管理连接和网络 - { {3}}。

如果您习惯于更多类似JDBC的访问,则可以根据自己的喜好找到http://docs.oracle.com/javase/6/docs/api/javax/naming/ldap/LdapContext.html。在那里你有完全在你控制之下的连接,你可以像在JDBC中一样对待它们。您可以使用任何您喜欢的池库。

答案 2 :(得分:0)

不知道具体要求我将核心问题解释为“何时打开/关闭连接”。

我的水晶球告诉我你可能想要使用连接池。是的,您不会显式关闭连接,因为这是由池处理的,但这可能适合您的任务。这很容易:

// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");

complete source code中引用了Oracle's basic LDAP tutorial

答案 3 :(得分:0)

没有弹簧(被禁止),我会很快实现simillar:

  • (当懒惰时)创建一个简单的回调接口(例如你可以在spring找到 - JpaCallback.execute(EntityManager em)) - 但是对于LDAP - MyLdapCallback.execute(LdapConnection连接) - 对LdapConnection的整数你可以想象你需要的任何东西 - 来自OpenLdap或SDK Context的对象。像(仅用于演示)的东西:
    
...
interface LdapCallback<T> {
    T execute(DirContext ctx) throws NamingException, IOException;
}
...
private <T> T execute(LdapCallback<T> callback) throws NamingException, IOException {
    T result = null;
    LdapContext ctx = new InitialLdapContext();
    try {
        result = callback.execute(ctx);
    } finally {
        if (tls != null) {
            tls.close();
        }
        ctx.close();
    }
    return result;
}
...

完成后,您将为每个Ldap调用创建一个匿名类,并通过execute(回调)调用回调。

  • (有更多时间)实现广告1. +创建AOP,它将包含带有注释的方法,该方法本身将在上面的包装器中执行我的方法(在我的代码中没有明确地这样做)