5

目前从 java 我正在使用以下代码连接到 LDAP,非常典型的示例:

    Hashtable<String, String> env = new Hashtable<String, String>();

    env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
    env.put(Context.PROVIDER_URL, url);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");
    env.put(Context.SECURITY_PRINCIPAL, user);
    env.put(Context.SECURITY_CREDENTIALS, password);

    LdapContext ctx = null;

    try
    {
        ctx = new InitialLdapContext(env, null);
        return true;
    }
    catch (NamingException ex)
    {
        return false;
    }
    finally
    {
        if (ctx != null)
        {
            try {
                ctx.close();
            } catch (NamingException e) {
                log.warn(e.getMessage());
            }
        }
    }

这适用于对用户进行身份验证。但是,LDAP 管理员告诉我,当绑定不成功时,我没有正常断开连接。LDAP 端的错误是(例如):

[24/Jan/2013:13:20:44 -0500] conn=249 op=-1 msgId=-1 - 从 [ipaddress]:44724 关闭 - A1 - 客户端中止连接 -

他还说,当身份验证成功时,断开连接是优雅的。我想这是因为我ctx.close()在那种情况下这样做。

但是,当身份验证失败时,实际上会从new InitialLdapContext(env, null)线路中抛出一个异常。因此不会返回任何上下文,并且不会在任何上下文上调用关闭。

有没有办法在尝试身份验证之前检索某种连接对象,以便我可以在之后关闭它,无论身份验证是否成功?

4

3 回答 3

3

他为什么要在优雅和不优雅的收场之间在意?显然,您的收盘是在唯一相关的情况下执行的:您成功的情况。在另一种情况下,没有什么可以关闭,所以你什么都不能调用。在另一种情况下,JNDI LDAP 提供者将其关闭,很明显,它正在执行中止关闭。这一切都在 JNDI LDAP 提供者的底层。你无能为力。我建议他找点别的事情来担心,这实际上很重要。

于 2013-01-24T23:57:46.217 回答
2

搜索 LDAP 正常返回

NamingEnumeration<SearchResult> results

您还需要关闭():

} finally {
            if(results != null) {
                try {
                    results.close();
                } catch (NamingException e) {
                    LOG.error("Error closing LDAP results", e);
                }
            }
于 2014-09-24T12:54:48.937 回答
0

在添加任何身份验证详细信息之前构造上下文对象。然后,使用 addToEnvironment 添加凭据。最后,执行一个非常简单的搜索(我的方法是查找用户名的 distinctName 属性)。如果凭据不好,搜索将失败,并且您仍然需要关闭上下文对象。

这种方法的另一个好处是:您可以维护一个上下文对象池,并避免不断地连接/断开连接以执行身份验证。

Hashtable<String,String> environment = new Hashtable<String,String>();
environment.put("java.naming.provider.url", url);
environment.put("java.naming.factory.initial", "com.sun.jndi.ldap.LdapCtxFactory");

InitialLdapContext context = new InitialLdapContext(environment, null);

...

context.addToEnvironment("java.naming.security.principal", principal);
context.addToEnvironment("java.naming.security.credentials", credentials);

...

// execute some kind of search, based on your needs
于 2016-02-17T01:24:43.970 回答