【问题标题】:Connect LDAP from Spring从 Spring 连接 LDAP
【发布时间】:2013-01-05 14:13:16
【问题描述】:

我必须实现一个基于 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 的连接会太多...

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

提前谢谢你:-)

【问题讨论】:

    标签: spring ldap jndi


    【解决方案1】:

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

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

    特别是如果您不熟悉 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();
            }
         });
    

    【讨论】:

      【解决方案2】:

      没有弹簧(被禁止),我会很快实现类似的东西:

      • (懒惰的时候)创建一个简单的回调接口(比如你可以在spring中找到——JpaCallback.execute(EntityManager em))——但是对于LDAP——MyLdapCallback.execute(LdapConnection connection)——而不是LdapConnection你可以想象任何你需要的东西——来自 OpenLdap 或 SDK 上下文的对象。类似的东西(仅用于演示):
      ...
      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(callback) 调用回调。

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

      【讨论】:

        【解决方案3】:

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

        如果您习惯了更多类似 JDBC 的访问,您可能会发现http://www.openldap.org/jldap/ 更符合您的喜好。在那里,您可以完全控制连接,并以与 JDBC 中相同的方式对待它们。你可以使用任何你喜欢的池化库。

        【讨论】:

        • 问题不在于用于连接 ldap 的方式。就我而言,我必须使用 JNDI(这是一个类项目)。我的问题是如何从我的控制器访问我的类的方法,同时巧妙地管理 ldap 连接。
        【解决方案4】:

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

        我的水晶球告诉我你可能想要使用连接池。诚然,您不会明确关闭连接,因为这是由池处理的,但这对于您的分配可能没问题。这很容易:

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

        complete source codeOracle's basic LDAP tutorial 中被引用。

        【讨论】:

          猜你喜欢
          • 2011-03-30
          • 1970-01-01
          • 1970-01-01
          • 2015-01-17
          • 2011-07-12
          • 2016-04-13
          • 1970-01-01
          • 2015-01-18
          • 2016-07-18
          相关资源
          最近更新 更多