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;
}
}