public static void main(String[] args)
{
String INITCTX = "com.sun.jndi.ldap.LdapCtxFactory";
String MY_HOST = "ldap://Localhost:1389";
String MGR_DN = "cn=John,ou=Users,o=IT,dc=QuizPortal";
String MGR_PW = "password";
//Identify service provider to use
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, INITCTX);
env.put(Context.PROVIDER_URL, MY_HOST);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, MGR_DN);
env.put(Context.SECURITY_CREDENTIALS, MGR_PW);
try
{
// Create the initial directory context
InitialDirContext initialContext = new InitialDirContext(env);
System.out.println("Context Sucessfully Initialized");
}
catch(Exception e)
{
System.err.println(e);
}
}
I would like to ask when I set the MGR_DN = "cn=John,ou=Users,o=IT,dc=QuizPortal"
to MGR_DN = "uid=103,ou=Users,o=IT,dc=QuizPortal"
. Basically changing from cn to uid, I would encounter an error
javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
I am authenticated when is specified as cn=John
but not uid=103
. Am I not allowed to specify by uid?
JNDI does for LDAP what JDBC does for Oracle -- it provides a standard API for interacting with naming and directory services using a service provider interface (SPI), which is analogous to an JDBC driver. LDAP is a standard way to provide access to directory information.
Both the JNDI and LDAP models define a hierarchical namespace in which you name objects. Each object in the namespace may have attributes that can be used to search for the object. At this high level, the two models are similar, so it is not surprising that the JNDI maps well to the LDAP.
In order to authenticate a user with an LDAP directory you first need to obtain their DN as well as their password. With a login form, people typically enter a simple identifier such as their username or email address. You don't expect them to memorise the DN of their directory entry.
In LDAP, authentication is supplied in the "bind" operation. LDAP v3 supports three types of authentication: anonymous, simple and SASL authentication.
If you don't know the exact DN in advance, you should do a search in the LDAP directory first. This can be done more or less like this (make sure you catch the relevant exceptions):
Properties env = new Properties();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, ldapServerUrl);
env.put(Context.SECURITY_AUTHENTICATION, "none");
SearchControls searchCtrls = new SearchControls();
searchCtrls.setReturningAttributes(new String[] {});
searchCtrls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(&(cn=" + identifier + "))";
DirContext ctx = null;
ctx = new InitialDirContext(env);
NamingEnumeration<SearchResult> answer = ctx.search(
ldapBaseDN, filter, searchCtrls);
String fullDN = null;
if (answer.hasMore()) {
fullDN = answer.next().getNameInNamespace();
ctx.close();
ctx = null;
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, fullDN);
env.put(Context.SECURITY_CREDENTIALS, password);
ctx = new InitialDirContext(env);
return true;
}
// Exception otherwise ...
Here, the search filter is "(&(cn=" + identifier + "))"
(so, for example (&(cn=John))
), but you could use the uid
instead. Uniqueness of the results depends on the configuration of the LDAP server. The base DN also depends on the way it's set up (it could be ou=Users,o=IT,dc=QuizPortal
in your example).
You have to specify the DN or distinguished name. That's the name the user is bound as in the directory. You can't just select any chain of attributes. If your users are bound via the 'cn' attribute then only the 'cn' attribute is part of the DN.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With