18

我正在维护一些遗留的 Java LDAP 代码。我对 LDAP 几乎一无所知。

下面的程序基本上只是将用户名和密码发送到 LDAP 服务器,如果凭据良好,则会收到通知。如果是,它打印出从 LDAP 服务器接收到的 LDAP 属性,如果不是,它打印出一个异常。

如果输入错误的密码,一切正常。抛出“无效凭据”异常。但是,如果向 LDAP 服务器发送空白密码,仍然会进行身份验证,仍然会返回 LDAP 属性。

这种不愉快的情况是由于 LDAP 服务器允许空白密码,还是需要调整下面的代码,这样一个空白密码会以这种方式被馈送到 LDAP 服务器,所以它会被拒绝?

我确实有数据验证。我在测试环境中将其取下来解决另一个问题并注意到了这个问题。我不希望在数据验证下出现这个问题。

非常感谢您提供任何信息

import javax.naming.*;
import javax.naming.directory.*;
import java.util.*;
import java.sql.*;

public class LDAPTEST {

    public static void main(String args[]) {

        String lcf                = "com.sun.jndi.ldap.LdapCtxFactory";
        String ldapurl            = "ldaps://ldap-cit.smew.acme.com:636/o=acme.com";
        String loginid            = "George.Jetson";
        String password           = "";
        DirContext ctx            = null;
        Hashtable env             = new Hashtable();
        Attributes attr           = null;
        Attributes resultsAttrs   = null;
        SearchResult result       = null;
        NamingEnumeration results = null;
        int iResults              = 0;
        int iAttributes           = 0;


        env.put(Context.INITIAL_CONTEXT_FACTORY, lcf);
        env.put(Context.PROVIDER_URL, ldapurl);
        env.put(Context.SECURITY_PROTOCOL, "ssl");
        env.put(Context.SECURITY_AUTHENTICATION, "simple");
        env.put(Context.SECURITY_PRINCIPAL, "uid=" + loginid + ",ou=People,o=acme.com");
        env.put(Context.SECURITY_CREDENTIALS, password);
        try {

            ctx     = new InitialDirContext(env);
            attr    = new BasicAttributes(true);
            attr.put(new BasicAttribute("uid",loginid));
            results = ctx.search("ou=People",attr);

            while (results.hasMore()) {
                result       = (SearchResult)results.next();
                resultsAttrs = result.getAttributes();

                for (NamingEnumeration enumAttributes  = resultsAttrs.getAll(); enumAttributes.hasMore();) {
                    Attribute a = (Attribute)enumAttributes.next();
                    System.out.println("attribute: " + a.getID() + " : " + a.get().toString());
                    iAttributes++;


                }// end for loop

                iResults++;
            }// end while loop

            System.out.println("Records  == " + iResults + " Attributes: " + iAttributes);

        }// end try
        catch (Exception e) {
            e.printStackTrace();
        }



    }// end function main()
}// end class LDAPTEST
4

4 回答 4

21

不幸的是,使用 DN 和空密码进行身份验证是 LDAP 的不足之处之一,并且会导致来自服务器的“未经身份验证”的肯定响应。一些 LDAP 服务器具有配置选项来禁用在最新版本的 LDAPv3 (RFC 4511) 中不鼓励的行为,甚至默认禁用它。

最终,客户端应用程序应检查输入参数并确保密码不为空。

于 2012-09-11T13:21:14.537 回答
9

您需要从简单更改身份验证方法(无论如何这在生产环境中都不能使用,至少在没有 SSL 的情况下不能使用)。

正如这里所说:http: //docs.oracle.com/javase/jndi/tutorial/ldap/security/simple.html

如果您向 Context.SECURITY_CREDENTIALS 环境属性提供空字符串、空字节/字符数组或 null,则身份验证机制将为“无”。这是因为 LDAP 要求密码为非空以进行简单身份验证。如果未提供密码,协议会自动将身份验证转换为“无”。

于 2012-09-10T22:19:49.027 回答
4

有两种类型的 BIND 操作,simpleSASL. 在简单 BIND 的情况下,有四种可能性:

  • 空 DN 和空密码: anonymous,不进行身份验证。这是初始状态,也是服务器收到 BIND 请求时的状态
  • 非空 DN,空密码:unauthenticated,不进行身份验证
  • non-empty DN, non-emptypassword:正常情况,尝试认证
  • 空 DN,非空密码:LDAP 标准中未定义服务器行为。不进行身份验证。

最初建立连接时,连接是anonymous. 每个 BIND 请求都将连接状态重置为anonymous。每个成功的 BIND 请求都会将连接的授权状态更改为专有名称的授权状态。每个不成功的 BIND 请求都会使连接未经身份验证。

BIND 的语义在LDAP 中定义: Authentication

于 2012-09-11T12:29:55.093 回答
1

当您发送“空”密码时会发生什么身份验证(即绑定)以匿名方式完成。

可以修改您的代码以检测空密码或用户 ID 以停止此活动。

一些 LDAP 实现可以停止任何匿名绑定。

于 2012-09-11T10:27:18.637 回答