我是 LDAP 新手,并且正在将它与com.sun.jndi.ldap
jar 一起使用。
我有一个登录页面,用户在其中输入用户名和密码。我的工作是使用 LDAP 中的数据验证凭据。
到目前为止,我已经连接到 LDAP 服务器,验证并检索了 uid。
现在我想比较用户输入的密码和 LDAP 中的密码(密码是私有的,即在查询用户 ID 时无法查看)。
有没有办法比较这两个密码?
我们有几个使用绑定作为用户的示例。你应该被别人提到,做一个绑定,永远不要比较密码。密码比较是一种不好的做法,不应使用,因为在对密码属性执行比较请求时,可能会绕过一些内置的 LDAP 服务器实现功能,例如密码过期和入侵者检测。
Java LDAP API 提供search
依次引起 LDAP 比较的操作。这是一个相同的例子。
如果在您的应用程序中有一个使用 Spring Security 的选项,它有一个模块可以让您将身份验证与 LDAP 集成。
如果你真的想比较一个字段(不限于用户名和密码),你可以在方法上使用以下包装器search
:
public boolean compare(LdapContext ctx, String dn, String filter) {
NamingEnumeration<SearchResult> answer = null;
try {
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.OBJECT_SCOPE);
searchCtls.setReturningAttributes(new String[0]);
answer = ctx.search(dn, filter, searchCtls);
if (answer == null || !answer.hasMore()) {
return false; // E.g.: wrong filter
}
} catch (NamingException ex) {
return false; // E.g.: wrong DN
}
return true;
}
ctx
可能在哪里:
LdapContext ctx = new InitialLdapContext(getEnvironment(userName, password), null);
getEnvironment
方法可以是:
private Hashtable<String, Object> getEnvironment(String userName, String password) {
Hashtable<String, Object> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, LDAP_HOST_389);
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, password);
return env;
}
如果你调用compare
上面的方法,你会得到:
false
如果出现问题(例如:无效dn
,无效filter
)true
除此以外。在这种情况下,如果您检查方法answer
中的compare
,您将看到:
SearchResult sr = answer.next();
sr.getName(); // this is empty
sr.getAttributes(); // No attributes
您还可以查看Oracle 的 LDAP 比较文档。
你问错问题了。使用 LDAP 的正确方法是使用用户的凭据而不是您自己的凭据“绑定”到目录。在 JNDI 中,这对应于LdapContext.reconnect()
操作,在将用户的凭据设置为上下文环境之后Context.SECURITY_PRINCIPAL
,Context.SECURITY_CREDENTIALS.
这会导致 LDAP 服务器根据需要进行密码比较。
如果我理解正确,您正在尝试比较用户输入的密码和 Java 代码中 LDAP 中的密码。这在 JAVA 中是不可能的,因为 java 没有从 LDAP 检索密码的选项。我们只能要求 LDAP 验证用户输入的详细信息。此外,LDAP 中的密码不会以纯文本形式存储,而是会被加密并存储。