配置信息config.xml
<pre name="code" class="java">Conf> <ADinformation> <ADldapHost>ldap://11.241.14.333:389</ADldapHost> <ADDN>CN=AAA,OU=BBB,OU=CCC,DC=DDD,DC=EEE</ADDN> <ADpassword>ZXC</ADpassword> <ADsearchBaseDN>ou=CCC,dc=DDD,dc=com</ADsearchBaseDN> </ADinformation> </Conf>
一初始化:
import java.util.Map; import java.util.Properties; import javax.naming.Context; import play.mvc.Controller; /** * This class is used to return informations for an AD connection. * 初始化 * **/ public class ADconnect { public static Properties getProps()throws Exception{ try{ Map<String, String> map = Readxml.getXmlInfo("config.xml"); String ldapHost=map.get("ADldapHost"); String DN=map.get("ADDN"); String password=map.get("ADpassword"); String searchBaseDN=map.get("ADsearchBaseDN"); Properties props=new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); props.put(Context.PROVIDER_URL, ldapHost); props.put("java.naming.ldap.version", "3"); props.put(Context.SECURITY_PRINCIPAL, DN); props.put(Context.SECURITY_CREDENTIALS, password); props.put("ADsearchBaseDN", searchBaseDN); props.put(Context.REFERRAL,"follow"); return props; }catch(Exception ex) { throw ex; } } }
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_22_5959525" name="code" class="java">
二:在AD环境中认证账户信息
import java.util.Map; import java.util.Properties; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import org.xml.sax.SAXException; /** * This class is used to authenticate or check informations for an account. **/ public class ADauthenticate extends Controller { public static Boolean checkByPassword(String password) throws NamingException, SAXException, IOException { Map<String, String> map = Readxml.getXmlInfo("config.xml"); String DistinguishedName = ""; Object obj = Cache.get("DistinguishedName"); if (obj != null) { DistinguishedName = obj.toString(); } else { DistinguishedName = session("DistinguishedName"); } String DN = DistinguishedName; String url = map.get("ADldapHost"); // get DirContext for AD connect Properties props = new Properties(); DirContext ctx; props.put(Context.SECURITY_AUTHENTICATION, "simple"); props.put(Context.SECURITY_PRINCIPAL, DN); props.put(Context.SECURITY_CREDENTIALS, password); props.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); props.put(Context.PROVIDER_URL, url); try { ctx = new InitialDirContext(props); ctx.close(); //if return true, this account has successfully login. return true; } catch (NamingException err) { //else, it failed to login. return false; } } /** * This function is used to check informations of an account. */
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_10_8218727" name="code" class="java">//将用户的各个属性以变量形式声明在类Authbean里 public static Boolean checkInfo(Authbean Info) throws Exception { try { ADsearch ad = new ADsearch(); String answer = ad.searchResult(session("AccountID"), (ADsearch.searchForWhat.S_ANSWER)); if (!Info.answer.equals(answer)) { //got wrong informations. return false; } }catch(Exception ex) { throw ex; } //information matches that in AD. return true; } }
</pre>三:AD修改关键代码<pre>
<pre name="code" class="java"> public class ADmodify { public enum modifyWhat{ M_LOCK, M_UNLOCK, M_UNLOCK2, M_QUESTION, //问题 M_ANSWER, //回答 } /** * This function is used to do simple AD modifies */ public static void modifyAccount(modifyWhat What,String content) throws Exception{ Properties props = null; try { ADsearch ad=new ADsearch(); int i; props = ADconnect.getProps(); ModificationItem[] mods = new ModificationItem[1]; Attribute attr2Change = null; boolean flg=false; switch(What){ case M_LOCK: i=Integer.parseInt(ad.searchResult(String.valueOf(Cache.get("AccountID")), ADsearch.searchForWhat.S_USERACCOUNTCONTROL)); attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i|2)); break; case M_UNLOCK: i=Integer.parseInt(ad.searchResult(String.valueOf(Cache.get("AccountID")), ADsearch.searchForWhat.S_USERACCOUNTCONTROL)); if(i%4!=0){ attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i-2)); } else{ attr2Change = new BasicAttribute("userAccountControl", String.valueOf(i)); } flg=true; break; case M_UNLOCK2: attr2Change=new BasicAttribute("lockoutTime","0"); break; case M_QUESTION: attr2Change = new BasicAttribute("extensionAttribute1", content); break; case M_ANSWER: attr2Change = new BasicAttribute("extensionAttribute2", content); break; default: break; } DirContext ctx = new InitialDirContext(props); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr2Change); String DistinguishedName = ""; Object obj = Cache.get("DistinguishedName"); if (obj != null){ DistinguishedName = obj.toString(); }else{ DistinguishedName = session("DistinguishedName"); } ctx.modifyAttributes(DistinguishedName, mods); if(flg){ modifyAccount(modifyWhat.M_UNLOCK2,""); flg=false; } }catch(Exception ex){ throw ex; } } };
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_14_6222669" name="code" class="java">四:AD 查找
<pre name="code" class="java">import java.util.Enumeration; import java.util.Properties; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.DirContext; import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; /** * This class is used to search account informations **/ public class ADsearch { public String searchType="person"; public String searchAttr="sAMAccountName"; public enum searchForWhat{ S_EXIST, S_LOCKED, S_INITIAL, S_DISTINGUISHEDNAME, S_QUESTION, S_ANSWER, S_USERACCOUNTCONTROL, }; /** * return a search result value according to the needs. * @param searchTxt * search text * @param What * attribute to search for * @return String * search result values * @throws Exception */ public String searchResult(String searchTxt,searchForWhat What) throws Exception{ Properties props= ADconnect.getProps(); String result=""; try{ DirContext ctx = new InitialDirContext(props); String searchFilter; searchFilter = "(&(objectClass="+searchType+")("+searchAttr+"="+ searchTxt+"))"; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration<?> searchResultEnum = ctx.search(props.getProperty("ADsearchBaseDN"),searchFilter,searchControls); //switch Search Functions switch (What){ case S_EXIST: result=existSearch(searchResultEnum,ctx); break; case S_LOCKED: result=lockedSearch(searchResultEnum,ctx); break; case S_INITIAL: result=initialSearch(searchResultEnum,ctx); break; case S_DISTINGUISHEDNAME: result=otherSearch("distinguishedName",searchResultEnum,ctx); break; case S_QUESTION: result=otherSearch("extensionAttribute1",searchResultEnum,ctx); break; case S_ANSWER: result=otherSearch("extensionAttribute2",searchResultEnum,ctx); break; case S_USERACCOUNTCONTROL: result=otherSearch("userAccountControl",searchResultEnum,ctx); break; default: break; } //end of the switched function }catch(Exception ex){ throw ex; } return result; } /** * Decide whether this id exists */ private String existSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx) throws NamingException { try { if(searchResultEnum.hasMore()){ //id exists. return "true"; } //id non-exists. return "false"; } catch(NamingException ex){ throw ex; } } /** * Decide whether this id is locked. * @return String * "true" represents "locked" while "false" represents "unlocked" * @throws NamingException */ private String lockedSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx) throws NamingException { try { if(searchResultEnum.hasMore()){ SearchResult searchResult = (SearchResult) searchResultEnum.next(); NamingEnumeration<?> names = searchResult.getAttributes().getAll(); while(names.hasMore()){ Attribute attr=(Attribute)names.nextElement(); //decide whether this id is active or not if(attr.getID().equals("lockoutTime")){ Enumeration<?> attrValEnum=attr.getAll(); if (attrValEnum.hasMoreElements()) { String elem = (String) attrValEnum.nextElement(); if(elem!=null && !elem.equals("0")){ //if return true, this account is locked. return "true"; } } } } } //else, this account is not locked. return "false"; } catch(NamingException ex){ throw ex; } } /** * Decide whether this id is the first time to login. */ private String initialSearch(NamingEnumeration<?> searchResultEnum,DirContext ctx) throws NamingException{ try { if(searchResultEnum.hasMore()){ SearchResult searchResult = (SearchResult) searchResultEnum.next(); NamingEnumeration<?> names = searchResult.getAttributes().getAll(); while(names.hasMore()){ Attribute attr=(Attribute)names.nextElement(); if(attr.getID().equals("otherMobile")) return "false"; } } return "true"; //id first login } catch(NamingException ex){ throw ex; } } /** * Return an attribute value of a user. */ private String otherSearch(String search,NamingEnumeration<?> searchResultEnum,DirContext ctx) throws NamingException{ try { String result=""; if(searchResultEnum.hasMore()){ SearchResult searchResult = (SearchResult) searchResultEnum.next(); NamingEnumeration<?> names = searchResult.getAttributes().getAll(); while(names.hasMore()){ Attribute attr=(Attribute)names.nextElement(); if(attr.getID().equals(search)){ Enumeration<?> attrValEnum=attr.getAll(); if (attrValEnum.hasMoreElements()) { result = (String)attrValEnum.nextElement(); } } } } return result; } catch(NamingException ex){ throw ex; } } }
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_17_9036160" name="code" class="java">五:AD账户密码重置
<pre name="code" class="java">//This class is used to reset password for an account. public class ADresetpwd { public LdapContext ctx = null; /** * This function is used to reset password for an account. */ public boolean resetPassword(String distinguishedName,String newPassword){ try{ initial_Ldap(); mod_Pwd(distinguishedName,newPassword); close_Ldap(); }catch(Exception e){ e.printStackTrace(); //if return false, this action has failed. return false; } //if return true, password has been reset successfully. return true; } /** * This function is used to connect AD using the security mode. * * @throws Exception */ private void initial_Ldap() throws Exception { System.setProperty("javax.net.ssl.trustStore", Utils.keystore); System.setProperty("javax.net.ssl.trustStorePassword", Utils.keyPassword); Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, Utils.adminName); env.put(Context.SECURITY_CREDENTIALS, Utils.adminpassword); env.put(Context.SECURITY_PROTOCOL, "ssl"); env.put(Context.PROVIDER_URL, Utils.ldapURL); try { ctx = new InitialLdapContext(env, null); } catch (NamingException e) { e.printStackTrace(); throw e; } }
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_20_3037349" name="code" class="java"><span style="white-space:pre"> </span>//class Utils <span style="white-space:pre"> </span>//public static final String adminName = "[email protected]"; <span style="white-space:pre"> </span>//public static final String adminpassword = "mmmmm"; <span style="white-space:pre"> </span>//public static final String keystore = "c:/silverca.keystore"; <span style="white-space:pre"> </span>//public static final String keyPassword = "silver"; <span style="white-space:pre"> </span>//public static final String ldapURL ="ldaps://11.55.222.333:444"; /** * This function is used to modify password for an account. */ private void mod_Pwd(String username, String password) throws UnsupportedEncodingException, NamingException { ModificationItem[] mods = new ModificationItem[1]; String newQuotedPassword = "\"" + password + "\""; try { byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword)); ctx.modifyAttributes(username, mods); } catch (UnsupportedEncodingException e1) { e1.printStackTrace(); throw e1; } catch (NamingException e2) { e2.printStackTrace(); throw e2; } } /** * This function is to close an AD connection. * * @throws NamingException */ private void close_Ldap() throws NamingException{ try { ctx.close(); } catch (NamingException e) { e.printStackTrace(); throw e; } } }
</pre><pre code_snippet_id="363364" snippet_file_name="blog_20140526_22_5959525" name="code" class="java">