2

我有一个网页页面来管理活动目录组,并且在此页面的初始化中,我使用 jndi 连接到 ldap 并将 ldap 上下文保存在 http 会话中。

这是我连接到 ldap 的方式:

 public static LdapContext connectToLdap(String host,
            String userDN, String userPassword,
            boolean ssl) throws Exception {

        System.out.println("connectToLdap");

        String hostPrefix = "ldap";
        String ldapPort = "389";
        if (ssl) {
            hostPrefix = "ldaps";
            ldapPort = "636";
        }
        String providerUrl = hostPrefix + "://" + host + ":" + ldapPort;
        //System.out.println("####### LDAP URL: " + providerUrl);
        LdapContext ldapContext;
        Hashtable<String, String> ldapEnv = new Hashtable<String, String>(11);
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, providerUrl);
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, userDN);
        ldapEnv.put(Context.SECURITY_CREDENTIALS, userPassword);
        ldapEnv.put("com.sun.jndi.ldap.read.timeout", 1000 * 10 + "");
        if (ssl) {
            ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        }
        ldapEnv.put(Context.REFERRAL, "ignore");
        try {
            ldapContext = new InitialLdapContext(ldapEnv, null);           
            System.out.println("success connection to ldap");
            return ldapContext;
        } catch (Exception e) {
            System.out.println("failure connection to ldap");
            e.printStackTrace();
            return null;
        }
    }
  • 我不关闭上下文,因为它将在用户会话期间重用。
  • 我将 ldapcontext 放在 session 中,这样我就不必频繁地为每个用户连接 ldap,每个用户每个会话只有一个连接。

问题:我注意到有时 10-15 分钟后,活动目录组的检索失败并且我得到异常:

javax.naming.CommunicationException: Connection reset [Root exception is java.net.SocketException: Connection reset]

任何想法为什么?请告知我为什么会遇到这个问题以及如何解决它。

4

1 回答 1

1

不要将 LdapContext 放在 HTTP 会话中,它不实现 Serializable 接口,因此不能保证它可以存储/恢复到会话。

想想看,如果会话要存储在数据库中或复制到另一台服务器 LdapContext 将被转换为字节,以及它引用的任何套接字描述符,当你从字节恢复它们时,这将如何工作?

如果您需要长期连接,请将其放在单例中。

除此之外,服务器和网络设备通常会关闭 [他们认为是] 不活动的网络连接,因此任何长期连接都需要进行测试或保持活动状态。

如果它仍然相关,我建议您使用(GPLv2,LGPLv2.1 许可)UnboundID LDAP SDK for Java(无从属关系),它比随附的 JNDI 实现更好地处理连接 连接测试。

于 2014-11-13T11:36:57.197 回答