2014年4月22日 星期二

JAVA 利用 JNDI 做 LDAP 登入認證

其實要用JNDI做AD認證很簡單,只需要下面這樣


Hashtable env = new Hashtable ();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "LDAP://<LDAP Host>:<port>");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, email);
env.put(Context.SECURITY_CREDENTIALS, password);
new InitialLdapContext(env);


但這篇要寫的是針對LDAP認證,因為偉大的MIS不會設定LDAP使用自訂的認證機制
所以認證的帳號我只能使用DN,不能用Email...


好~進入正題

基本是在系統上,使用者登入絕對是打 Email,
絕對不可能要求使用者去記得那一長串又臭又長的 DN
所以程式要做的事就很明瞭了,就是將 Email 轉成 DN
其實也就是先到 LDAP 下用 Mail 這個屬性找到該名使用者
拿到 SearchResult 以後 getName


首先,還是要先 init ,連線到 LDAP
跟上面AD認證不一樣的是,
這次不用先給SECURITY_PRINCIPAL跟SECURITY_CREDENTIALS


       private String BASEDN = "dc=example,dc=com";
       private void initialData() throws NamingException {
Hashtable env = new Hashtable ();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, "LDAP://<LDAP Host>:<port>/");
env.put(Context.SECURITY_AUTHENTICATION, "simple");

ldapContext = new InitialLdapContext(env, connCtls);
}



接著這篇最重要的 Email 轉成 DN


private String getUserDN(String email) {
String userDN = null;

// Create the search controls
SearchControls searchCtls = new SearchControls();

// Specify the search scope
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);

// specify the LDAP search filter
// String searchFilter = "(&(objectClass=*))";
String searchFilter = "(&(ObjectClass=*)(mail=" + email + "))";

// Search for objects using the filter
NamingEnumeration answer;
try {
answer = ldapContext.search(BASEDN, searchFilter, searchCtls);

if (answer != null) {
// Loop through the search results
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
userDN = "";
userDN += sr.getName();
userDN += "," + BASEDN;
}
}

} catch (Exception e) {
}

return userDN;
}



主要的登入程式,沒什麼好說明的
就是設定完帳密,重新連線


public String auth(String email, String password) {
String userDN = getUserDN(email);

if(userDN==null) return "USERNAME_NOT_EXSIT";
try {
ldapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN);
ldapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ldapContext.reconnect(connCtls);
System.out.println(userDN + " is authenticated");
return "SUCCESS";
} catch (AuthenticationException e) {
return "AUTH_FALED";
} catch (NamingException e) {
return "AUTH_FALED";
}
}


沒有留言:

張貼留言