我正在维护一些旧的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
答案 0 :(得分:20)
不幸的是,使用DN和空密码进行身份验证是LDAP的难点之一,并导致服务器出现“未经身份验证的”肯定响应。 某些LDAP服务器具有配置选项,用于禁用最新版本的LDAPv3(RFC 4511)中不鼓励的行为,甚至默认情况下禁用该行为。
最终,客户端应用程序应检查输入参数并确保密码不为空。
亲切的问候,
朱利
答案 1 :(得分:8)
您需要更改简单的身份验证方法(无论如何不要在生产环境中使用,至少在没有SSL的情况下)。
如此处所述:http://docs.oracle.com/javase/jndi/tutorial/ldap/security/simple.html
如果提供空字符串,空字节/ char数组,或者为Context.SECURITY_CREDENTIALS环境属性提供null,则认证机制将为“none”。这是因为LDAP要求密码对于简单身份验证是非空的。如果未提供密码,协议会自动将身份验证转换为“无”。
答案 2 :(得分:3)
有两种类型的BIND操作,simple
和SASL
。在简单BIND的情况下,有四种可能性:
anonymous
,不进行身份验证。这是初始状态,也是服务器收到BIND请求时的状态unauthenticated
,不进行身份验证最初建立连接时,连接为anonymous
。每个BIND请求都会将连接状态重置为anonymous
。每个成功的BIND请求都会将连接的授权状态更改为可分辨名称的授权状态。每个不成功的BIND请求都会使连接保持未经身份验证。
BIND的语义在LDAP: Authentication
中定义答案 3 :(得分:1)
发送“空”密码时发生的情况是身份验证(即绑定)是匿名完成的。
您的代码可以修改为检测空密码或用户ID以停止此活动。
某些LDAP实现可以阻止任何匿名绑定。