1. 域服务器(dc=dctest,dc=com),安装证书服务,创建企业根证书,名称为dctest.com
则:cn=dctest.com,dc=dctest,dc=com
2. 申请证书类型域控制器的证书
3. 将企业根证书和域控制器证书导入到应用服务器cacerts
4. 在应用程序中,编写代码引用cacerts认证。
keytool
package bof.usermanager.auth.impl; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.naming.AuthenticationException; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.directory.Attribute; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.DirContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; import javax.naming.ldap.Control; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import com.report.service.PropertyItem; import com.report.vo.OrganizationalUnitDomain; import com.report.vo.UserDomain; /** * 功能:本操作类提供AD域用户的增、删、查、改功能 * 作者:陈艺武 * 日期:2010-4-13 */ public class LdapADManager { protected DataSourceConnectLDAPVO transientInstance = null; /** 用户的objectClass*/ private String default_objectclass = "user"; /**用户的默认根DN*/ private String default_base = "CN=Users,DC=all,DC=com"; /** 用户默认主键*/ private String key_index = "CN"; /** 用户默认密码属性.*/ private String pwd_index = "unicodePwd"; private Control[] connCtls = null; private static LdapADManager LdapADManager = null; private LdapADManager(){} public static LdapADManager getInstance(){ if(LdapADManager==null) LdapADManager = new LdapADManager(); return LdapADManager; } /** * 从连接池中获取一个连接. * * @return LdapContext * @throws NamingException */ public LdapContext getConnectionFromFool() throws NamingException { PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); String keystore = "c:/Java/jdk1.6.0_10/jre/lib/security/cacerts"; System.setProperty("javax.net.ssl.trustStore", keystore); Properties env = new Properties(); env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory"); env.put("com.sun.jndi.ldap.connect.pool", "true"); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PROTOCOL, "ssl"); //env.put("java.naming.referral", "follow"); env.put(Context.PROVIDER_URL, ldapProperty.getLdapURL()); connCtls = new Control[] { new LdapADManagerControl() }; return new InitialLdapContext(env, connCtls); } /** * 功能:校验用户登录. * @param userName * @param password * @return * * 作者:陈艺武 * 日期:Apr 13, 2010 */ public boolean authenticate(String userName, String password) { PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); String userDn = userName + "@" + ldapProperty.getDomain(); LdapContext ctx = null; try { ctx = getConnectionFromFool(); ctx.getRequestControls(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDn); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.reconnect(connCtls); return true; } catch (AuthenticationException e) { e.printStackTrace(); return false; } catch (NamingException e) { e.printStackTrace(); return false; } finally { try { ctx.close(); } catch (Exception e){ e.printStackTrace(); } } } /** * 功能:获取AD用户列表 * @return * * 作者:陈艺武 * 日期:Apr 12, 2010 */ public List listUser(){ PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); List list = new ArrayList(); LdapContext ctx = null; UserDomain user=null; String base = "OU=" + ldapProperty.getBase() + "," + ldapProperty.getDomainDC(); try{ ctx = this.getConnectionFromFool(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, ldapProperty.getUserName() + "@" + ldapProperty.getDomain()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, ldapProperty.getPassWord()); //base = "OU=北京华融综合投资公司,DC=bjhr,DC=com,DC=cn"; String filter = "(&(objectCategory=person)(objectClass=USER)(name=*))"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); //controls.setReturningAttributes(new String[] {"sAMAccountName", "displayName", "department"}); controls.setReturningAttributes(new String[] {"sAMAccountName", "cn"}); NamingEnumeration answer = ctx.search(base, filter, controls); while (answer.hasMore()) { user=new UserDomain(); SearchResult result = answer.next(); NamingEnumeration attrs = result.getAttributes().getAll(); int count=0; while (attrs.hasMore()) { Attribute attr = attrs.next(); if(count==0){ user.setUserName(attr.get().toString()); }else{ user.setUserAliasName(attr.get().toString()); } count++; } user.setNameSpace(ldapProperty.getDomain()); list.add(user); } }catch(Exception e){ e.printStackTrace(); } finally { try { ctx.close(); } catch (Exception e){ e.printStackTrace(); } } return list; } /** * 功能:查询组织单位列表 * @param ouName * @return * * 作者:陈艺武 * 日期:Apr 13, 2010 * 说明:base格式如:"OU=北京华融综合投资公司,DC=bjhr,DC=com,DC=cn"; */ public List listOrganizztionalUnit(String ouName){ PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); List list = new ArrayList(); LdapContext ctx = null; OrganizationalUnitDomain ouDomain = null; String base = "OU=" + ldapProperty.getBase() + "," + ldapProperty.getDomainDC(); try{ ctx = this.getConnectionFromFool(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, ldapProperty.getUserName() + "@" + ldapProperty.getDomain()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, ldapProperty.getPassWord()); String filter = "(&(objectClass=organizationalUnit)"; if(ouName!=null&&!ouName.equals("")) filter = filter + "(name=*" + ouName + "*)"; filter = filter + ")"; SearchControls controls = new SearchControls(); controls.setSearchScope(SearchControls.SUBTREE_SCOPE); controls.setReturningAttributes(new String[] {"name"}); NamingEnumeration answer = ctx.search(base, filter, controls); while (answer.hasMore()) { ouDomain = new OrganizationalUnitDomain(); SearchResult result = answer.next(); NamingEnumeration attrs = result.getAttributes().getAll(); int count=0; while (attrs.hasMore()) { Attribute attr = attrs.next(); if(count==0){ ouDomain.setOuName(attr.get().toString()); } count++; } list.add(ouDomain); } }catch(Exception e){ e.printStackTrace(); } finally { try { ctx.close(); } catch (Exception e){ e.printStackTrace(); } } return list; } /** * 功能:添加用户 * @param ou 组织单位:中投证券,销售部门 * @param department * @param realName 真实姓名,如:李伟 * @param userName 用户名,如:administrator * @param userPwd * @param adminUser * @param adminPwd * @return * * 作者:陈艺武 * 日期:Apr 12, 2010 */ public boolean addUser(String ou,String department,String realName, String userName, String adminUser,String adminPwd) { PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); LdapContext ctx = null; try { ctx = getConnectionFromFool(); Attributes attrs = new BasicAttributes(true); Attribute objclass = new BasicAttribute("objectclass"); setObjectclassToAttribute(objclass); attrs.put(objclass); attrs.put("sAMAccountName", userName); attrs.put("cn", realName); int UF_ACCOUNTDISABLE = 0x0002; int UF_PASSWD_NOTREQD = 0x0020; int UF_NORMAL_ACCOUNT = 0x0200; int UF_PASSWORD_EXPIRED = 0x800000; attrs.put("userAccountControl", Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD + UF_PASSWORD_EXPIRED + UF_ACCOUNTDISABLE)); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, adminUser + "@" + ldapProperty.getDomain()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, adminPwd); //String newUser = "CN="+realName+"," + cvtOuString(ou) + "," + ldapProperty.getDomainDC(); String newUser = "CN="+realName+"," + this.getFullOu(ctx, ou) + "," + ldapProperty.getDomainDC(); ctx.createSubcontext(newUser, attrs); ModificationItem[] mods = new ModificationItem[2]; String newQuotedPassword = "/"" + userName + "/""; byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword)); mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userAccountControl", Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWORD_EXPIRED))); ctx.modifyAttributes(newUser, mods); mods = null; return true; } catch (NamingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(ctx != null){ try{ ctx.close(); }catch(NamingException e){ e.printStackTrace(); } ctx = null; } } return false; } /** * 功能:管理员用户初始化用户密码 * @param sUserName * @param sNewPassword * @return * * 作者:陈艺武 * 日期:Apr 13, 2010 */ public boolean adminChangePassword(String adminUser,String adminPwd,String sUserName){ PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); LdapContext ctx = null; //不能从应用中修改超级管理员密码 if(sUserName!=null&&sUserName.equalsIgnoreCase("administrator")) return false; try { ctx = getConnectionFromFool(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, adminUser + "@" + ldapProperty.getDomain()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, adminPwd); ModificationItem[] mods = new ModificationItem[1]; String newQuotedPassword = "/"" + sUserName + "/""; byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword)); String cnUser = getUser(ctx,sUserName) + "," + ldapProperty.getDomainDC(); ctx.modifyAttributes(cnUser, mods); return true; }catch(Exception e){ e.printStackTrace(); } finally { try { ctx.close(); } catch (Exception e){ e.printStackTrace(); } } return false; } /** * 功能:用户修改密码 * @param sUserName * @param sOldPassword * @param sNewPassword * @return * * 作者:陈艺武 * 日期:Apr 9, 2010 */ public boolean userChangePassword(String sUserName, String sOldPassword, String sNewPassword){ PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); LdapContext ctx = null; String userNameAndDomain = sUserName + "@" + ldapProperty.getDomain(); //不能从应用中修改超级管理员密码 if(sUserName!=null&&sUserName.equalsIgnoreCase("administrator")) return false; try { ctx = getConnectionFromFool(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userNameAndDomain); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, sOldPassword); ModificationItem[] mods = new ModificationItem[2]; String oldQuotedPassword = "/"" + sOldPassword + "/""; byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE"); String newQuotedPassword = "/"" + sNewPassword + "/""; byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("unicodePwd", oldUnicodePassword)); mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword)); String cnUser = getUser(ctx,sUserName) + "," + ldapProperty.getDomainDC(); ctx.modifyAttributes(cnUser, mods); return true; }catch( Exception e){ e.printStackTrace(); }finally{ try{ ctx.close(); }catch(Exception e){ e.printStackTrace(); } } return false; } /** * 功能:修改用户信息 * @param attrs * @param userDN * @return * * 作者:陈艺武 * 日期:Apr 12, 2010 */ public boolean modify(Attributes attrs, String userDN) { LdapContext ctx = null; try { ctx = getConnectionFromFool(); attrs.remove(key_index); ctx.modifyAttributes(userDN, DirContext.REPLACE_ATTRIBUTE, attrs); return true; } catch (NamingException e) { System.err.println("Problem changing password: " + e); } catch (Exception e) { System.err.println("Problem: " + e); } finally { try { ctx.close(); } catch (Exception e) { e.printStackTrace(); } } return false; } /** * 功能:删除用户 * @param adminUser * @param adminPwd * @param userDN 用户登陆名 * @return * * 作者:陈艺武 * 日期:Apr 12, 2010 */ public boolean del(String adminUser,String adminPwd,String userName) { PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); LdapContext ctx = null; try { ctx = getConnectionFromFool(); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, adminUser + "@" + ldapProperty.getDomain()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, adminPwd); String adUser = getUser(ctx,userName) + "," + ldapProperty.getDomainDC(); ctx.destroySubcontext(adUser); return true; } catch (NamingException e) { System.err.println("Problem changing password: " + e); } catch (Exception e) { System.err.println("Problem: " + e); } finally { try { ctx.close(); } catch (Exception e) { e.printStackTrace(); } } return false; } private void setObjectclassToAttribute(Attribute objclass){ objclass.add("top"); objclass.add("person"); objclass.add("organizationalPerson"); objclass.add("inetorgperson"); } private String getUser(LdapContext ctx,String usr){ String userName = ""; String filter = "sAMAccountName="+usr; SearchResult si = getSearchResult(ctx,filter); if(si!=null) userName = si.getName(); return userName; } private String getFullOu(LdapContext ctx,String ou){ String userName = ""; String filter = "(&(objectClass=organizationalUnit)(name=" + ou + "))"; SearchResult si = getSearchResult(ctx,filter); if(si!=null) userName = si.getName(); return userName; } private SearchResult getSearchResult(LdapContext ctx,String filter){ SearchResult si = null; PropertyItem ldapProperty = (PropertyItem)AdProperties.getInstance().getPropertyItem().get(0); try { SearchControls constraints = new SearchControls(); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); NamingEnumeration en = ctx.search(ldapProperty.getDomainDC(), filter , constraints); // 查询所有用户 while(en!= null&&en.hasMoreElements()){ Object obj = en.nextElement(); if (obj instanceof SearchResult) { si = (SearchResult)obj; break; } } }catch (NamingException ex) { ex.printStackTrace(); } return si; } } class LdapADManagerControl implements Control { public byte[] getEncodedValue() { return null; } public String getID() { return "1.2.840.113556.1.4.1781"; } public boolean isCritical() { return true; } }