I do have a web-application, where users must log in. The password is stored in a LDAP server. All information about the LDAP server are stored in the application server (gl
i have done same in my application. following is the which might be useful to you.
package com.agileinfotech.bsviewer.servlet;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.naming.*;
import javax.naming.directory.*;
import java.util.Hashtable;
public class Login extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
public Login() {
super();
}
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
final String SUCCESS = "loin.jsp";
final String FAILURE = "Failure.html";
String strUrl = "login.html";
String username = request.getParameter("username");
String password = request.getParameter("password");
Hashtable env = new Hashtable(11);
boolean b = false;
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:10389");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "uid="+ username +",ou=system");
env.put(Context.SECURITY_CREDENTIALS, password);
try {
// Create initial context
DirContext ctx = new InitialDirContext(env);
// Close the context when we're done
b = true;
ctx.close();
} catch (NamingException e) {
b = false;
}finally{
if(b){
System.out.print("Success");
strUrl = SUCCESS;
}else{
System.out.print("Failure");
strUrl = FAILURE;
}
}
RequestDispatcher rd = request.getRequestDispatcher(strUrl);
rd.forward(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request,response);
}
}
This is a solution that can be used to authenticate a user with something else than the DN, for example with a uid
or sAMAccountName
.
The steps to do are:
sAMAccountName
)Code example:
public static boolean performAuthentication() {
// service user
String serviceUserDN = "cn=Mister Service,ou=Users,dc=example,dc=com";
String serviceUserPassword = "abc123#!$";
// user to authenticate
String identifyingAttribute = "uid";
String identifier = "maxdev";
String password = "jkl987.,-";
String base = "ou=Users,dc=example,dc=com";
// LDAP connection info
String ldap = "localhost";
int port = 10389;
String ldapUrl = "ldap://" + ldap + ":" + port;
// first create the service context
DirContext serviceCtx = null;
try {
// use the service user to authenticate
Properties serviceEnv = new Properties();
serviceEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
serviceEnv.put(Context.PROVIDER_URL, ldapUrl);
serviceEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
serviceEnv.put(Context.SECURITY_PRINCIPAL, serviceUserDN);
serviceEnv.put(Context.SECURITY_CREDENTIALS, serviceUserPassword);
serviceCtx = new InitialDirContext(serviceEnv);
// we don't need all attributes, just let it get the identifying one
String[] attributeFilter = { identifyingAttribute };
SearchControls sc = new SearchControls();
sc.setReturningAttributes(attributeFilter);
sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
// use a search filter to find only the user we want to authenticate
String searchFilter = "(" + identifyingAttribute + "=" + identifier + ")";
NamingEnumeration<SearchResult> results = serviceCtx.search(base, searchFilter, sc);
if (results.hasMore()) {
// get the users DN (distinguishedName) from the result
SearchResult result = results.next();
String distinguishedName = result.getNameInNamespace();
// attempt another authentication, now with the user
Properties authEnv = new Properties();
authEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
authEnv.put(Context.PROVIDER_URL, ldapUrl);
authEnv.put(Context.SECURITY_PRINCIPAL, distinguishedName);
authEnv.put(Context.SECURITY_CREDENTIALS, password);
new InitialDirContext(authEnv);
System.out.println("Authentication successful");
return true;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (serviceCtx != null) {
try {
serviceCtx.close();
} catch (NamingException e) {
e.printStackTrace();
}
}
}
System.err.println("Authentication failed");
return false;
}
You should be able to get the environment from the ldap context, clone it, and then put the principal and credentials for the user you want to check:
@Resource(name = "ldap/users")
private LdapContext ldapContext;
Hashtable environment = ldapContext.getEnvironment().clone();
environment.put(Context.SECURITY_PRINCIPAL, userDN);
environment.put(Context.SECURITY_CREDENTIALS, userPassword);
DirContext dirContext = new InitialDirContext(environment);
In real application LDAP servers, the password is stored in hashcode form and whenever any access manager takes the password from the user, that plain text password is again hashed with same key and checked to the one stored in the LDAP. So as such u can't get the plain password from LDAP server. So if you know the secret key, only then you can decrypt it.