1.安装AD
http://www.docin.com/p-191729140.html
问题:
安装 windows server 2008企业版,安装完后administrator密码为空,随后自己设置了符合密码策略的密码。服务器已经重启过。但在建AD时,确切说运行dcpromo后,提示administrator账号密码不符合要求,进行不下去。
解决方法:使用administrator登录系统,cmd运行如下命令:
C:\Users\Administrator>net user administrator /passwordreq:yes
命令成功完成。
安装VPN服务,开启AD后可以使用AD中配置的账号登录。
http://ce.sysu.edu.cn/hope2008/Education/ShowArticle.asp?ArticleID=8913
2.密码复杂度限制
http://www.cnblogs.com/ceachy/articles/2418657.html
以下步骤是为了实现java+ldap修改密码
3.安装证书服务
服务器管理器--角色--添加角色
http://blog.sina.com.cn/s/blog_67288bc90100jbwh.html
http://wenku.baidu.com/link?url=NGj3ZlGIBK3NQxXqFIgKDqGKelGz7EYhoyxpFcI5OrNpCG6li37TeAIPdVdXcmGN_ClX7LC7LtVpSml-fwjpBAgIX5qP5zeKCfGBE9oWYMO
4.向mmc中添加证书管理器
http://technet.microsoft.com/zh-cn/library/aa997890(EXCHG.80).aspx
5.java使用ldap修改用户密码
简单说就是三步:
1)通过mmc导出3中生成的ca证书
2)新建一个“个人”证书,类型为“域控制器身份验证”,并将其导出
3)将导出的两个证书使用java的keytool 分别导入到xx.keystore中
http://wenku.baidu.com/view/e30d73bcc77da26925c5b0c8.html
亲测,只导入1)中的证书就可以连接ssl了,将生成的security.keystore保存到指定路径即可。
keytool -import -alias local-ad-server -file "ad_server.cer" -keystore "security.keystore" -storepass changeit
6.cas+ldap
http://www.micmiu.com/enterprise-app/sso/sso-cas-ldap-auth/
7.通过IIS修改密码
windows server 2003 :http://wenku.baidu.com/view/00994454f01dc281e53af043.html
windows server 2008 :http://wenku.baidu.com/view/0698385fbe23482fb4da4c43.html
8.其它
LDAP百度百科:http://baike.baidu.com/view/159263.htm
AD常用命令:http://wenku.baidu.com/view/7196dc1fc281e53a5802ffcf.html
LdapUtil.java
package utils; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; 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.InitialLdapContext; import javax.naming.ldap.LdapContext; public class LdapUtil { public static LdapContext ctxTDS; /** * 连接LDAP */ public static LdapContext connetLDAP() throws NamingException { // 连接Ldap需要的信息 if (ctxTDS == null) { String ldapFactory = "com.sun.jndi.ldap.LdapCtxFactory"; String ldapUrl = "ldaps://169.254.105.76:636";// url,如果是ssl协议,端口是636 String ldapAccount = "CN=Administrator,CN=Users,DC=piaoyi,DC=local"; // 用户名 String ldapPwd = "LdapAdminPassword";// 密码 Hashtable<String, String> env = new Hashtable<String, String>(); env.put(Context.INITIAL_CONTEXT_FACTORY, ldapFactory); // LDAP server env.put(Context.PROVIDER_URL, ldapUrl); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, ldapAccount); env.put(Context.SECURITY_CREDENTIALS, ldapPwd); env.put(Context.REFERRAL, "follow"); // ssl证书 String keystore = "D:/ldap_modify/security.keystore";// 证书路径:cacerts文件路径 System.setProperty("javax.net.ssl.trustStore", keystore); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); env.put(Context.SECURITY_PROTOCOL, "ssl"); ctxTDS = new InitialLdapContext(env, null); System.out.println("##########Connet LDAP success!##########"); } return ctxTDS; } /** * 查询用户是否存在 * * @param propertityName * @param propertityValue * @return */ public static List<String> searchDNByPropertity(String propertityName, String propertityValue) { System.out.println("##########search LDAP start!##########"); List<String> list = new ArrayList<String>(); String userDN = ""; LdapContext ctx; try { ctx = connetLDAP(); String filter = "(&(objectClass=top)(objectClass=organizationalPerson)(" + propertityName + "=" + propertityValue + "))"; // 限制要查询的字段内容 String[] attrPersonArray = { "distinguishedName" }; SearchControls searchControls = new SearchControls(); searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); // 设置将被返回的Attribute searchControls.setReturningAttributes(attrPersonArray); // 三个参数分别为: // 上下文; // 要搜索的属性,如果为空或 null,则返回目标上下文中的所有对象; // 控制搜索的搜索控件,如果为 null,则使用默认的搜索控件 NamingEnumeration<SearchResult> answer = ctx.search( "DC=piaoyi,DC=local", filter.toString(), searchControls); // 输出查到的数据 while (answer.hasMore()) { SearchResult result = answer.next(); NamingEnumeration<? extends Attribute> attrs = result .getAttributes().getAll(); while (attrs.hasMore()) { Attribute attr = attrs.next(); userDN = (String) attr.get(); list.add(userDN); System.out.println(attr.getID() + "=" + attr.get()); } } System.out.println("##########search LDAP success!##########"); } catch (NamingException e) { // TODO Auto-generated catch block e.printStackTrace(); System.out.println("##########search LDAP fail!##########"); } // 设置过滤条件 return list; } /** * 修改用户属性,这种方式不能修改用户密码 * * @param userDN * @param map * @return */ public static boolean ModifyPropertiesByDN(String userDN, Map<String, String> map) { System.out.println("##########Data modify start!##########"); boolean result = true; LdapContext ctx; try { ctx = connetLDAP(); Attributes attrs = new BasicAttributes(true); for (Map.Entry<String, String> entry : map.entrySet()) { attrs.put(entry.getKey(), entry.getValue()); System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } ctx.modifyAttributes(userDN, DirContext.REPLACE_ATTRIBUTE, attrs); System.out.println("##########Data modify success!##########"); } catch (NamingException e) { // TODO Auto-generated catch block result = false; e.printStackTrace(); System.out.println("##########Data modify fail!##########"); } return result; } /** * 删除用户 * * @param userDN * @return */ public static boolean RemoveUserByDN(String userDN) { System.out.println("##########Data remove start!##########"); boolean result = true; LdapContext ctx; try { ctx = connetLDAP(); ctx.destroySubcontext(userDN); System.out.println("##########Data remove success!##########"); } catch (NamingException e) { // TODO Auto-generated catch block result = false; e.printStackTrace(); System.out.println("##########Data remove fail!##########"); } return result; } /** * 添加用户 * * javax.naming.OperationNotSupportedException: [LDAP: error code 53 - * 0000052D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM), data 0] * * 异常原因:密码不符合密码策略。 解决方式两种:1、把密码改得复杂点,大小写+数字+字母等等。 2、把AD密码策略去掉。 * * javax.naming.OperationNotSupportedException: [LDAP: error code 53 - * 0000001F: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM), data 0] * * 异常原因:必须使用证书才可修改AD密码。【注意:和上边的异常只差在 error code 后边的一长串码上,一定要看清楚了】 * 解决方式:配置成SSL证书形式。先创建用户,再修改密码。 * * @param userDN * @param cn * @param password * @param map * @return */ public static boolean AddUserByMap(String userDN, String cn, String password, Map<String, String> map) { System.out.println("##########Data add start!##########"); boolean result = true; LdapContext ctx; try { ctx = connetLDAP(); List<String> list = searchDNByPropertity("distinguishedName", userDN); if (list == null || list.size() == 0) { Attributes attrs = new BasicAttributes(true); Attribute objclass = new BasicAttribute("objectclass"); // 添加ObjectClass String[] attrObjectClassPerson = { "user", "organizationalPerson", "person", "top" }; Arrays.sort(attrObjectClassPerson); for (String ocp : attrObjectClassPerson) { objclass.add(ocp); } attrs.put(objclass); attrs.put("cn", cn); for (Map.Entry<String, String> entry : map.entrySet()) { attrs.put(entry.getKey(), entry.getValue()); System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue()); } ctx.createSubcontext(userDN, attrs); System.out.println("##########Data add success!##########"); if (password != null && !"".equals(password)) { modifyUserPasswordByDN(userDN, password); } } else { result = false; System.out.println("##########Data has exist!##########"); } } catch (NamingException e) { // TODO Auto-generated catch block result = false; e.printStackTrace(); System.out.println("##########Data add fail!##########"); } return result; } /** * 修改指定用户的密码 * * @param userDN * @param password * @return */ public static boolean modifyUserPasswordByDN(String userDN, String password) { System.out.println("##########Modify password start!##########"); boolean result = true; LdapContext ctx; try { ctx = connetLDAP(); ModificationItem[] mods = new ModificationItem[1]; String newQuotedPassword = "\"" + password + "\""; byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword)); ctx.modifyAttributes(userDN, mods); System.out.println("##########Modify password success!##########"); } catch (NamingException | UnsupportedEncodingException e) { // TODO Auto-generated catch block result = false; e.printStackTrace(); System.out.println("##########Modify password fail!##########"); } return result; } }