公司有几千号员工,使用ldap管理人员账号,开发了一套ad域的管理系统,方便人员入离职账号的统一管理、运维账号统一管理、单点登录管理、现将经生产环境运行稳定的代码放出,供大家参考,网上资料太少了,很多代码都用不了,基本一步一坑,
一些高级功能,可以加qq群:669293878 或微信:codearch讨论:例如ad域密码(unicodePwd)修改、查询翻页,对ad域的jdk免证书登录等。
本章是java对微软ActiveDirectory的增删改查操作,包含unicodePwd
package com.ad.ldaps;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.NameClassPair;
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;
/**
* @Description:对AD域用户的增删改查操作
* @author erek
* @date 2018-07-03
*/
public class AddUser {
//DirContext dc = null;
LdapContext dc = null;
String root = "ou=people,dc=domain,dc=com"; // LDAP的根节点的DC
//生产环境
final static String LDAPURL = "ldap://rwdc.sh.com:636";
final static String USER_NAME = "cn=it,ou=people,dc=domain,dc=com";
final static String USER_PWD = "nsexx2019";
final static String DEFAULT_PWD = "\"Goodnse@\"";//ad新建人员账号默认密码
//测试环境
// final static String LDAPURL = "ldap://10.100.52.237:636";
// final static String USER_NAME = "cn=administrator,cn=Users,dc=domain,dc=com";
// final static String USER_PWD = "123@abc";
/**
* @Description:程序入口
* @author
* @throws Exception
* @date 2019-07-03
*/
public static void main(String[] args) throws Exception {
AddUser utils = new AddUser();
utils.certinit();
String userName = "myh";
//0.用户连接
//utils.init();
//6.删除用户
//utils.delete(userName);
//1.添加用户
//utils.add(userName);
//7.修改密码失败
String oldPwd = "GoodSense@";
String newPwd = "123456@sensetime";
//utils.updatePWD(userName,oldPwd,newPwd);
//2.查找组织单位下的所有用户
//String base = "ou=robots,dc=domain,dc=sensetime,dc=com";
//base = utils.root;
//utils.searchInformation(base);
//3.查找组织单位下的某个用户
//SearchResult sr = utils.searchByUserName(utils.root, "liliang");
//System.out.println(sr.getName());
//4.修改用户属性
//utils.modifyInformation("testzhu", "M1380005");
//utils.updatePerson("testzhu");
//5.重命名用户
//utils.renameEntry("CN=testzhu,OU=maad,DC=case,DC=com", "CN=testzzz,OU=maad,DC=case,DC=com");
String[] s = {"lisi"};
for(String u : s) {
utils.searchByUserNameUidNumber(utils.root,u);
}
//utils.searchByUserNameUidNumber(utils.root,"suzehua");
//3.查找组织单位下的某个用户
//SearchResult sr = utils.searchByUserName(utils.root, "testaaa");
//System.out.println(sr.getName());
//utils.enablePerson("testzhu");
//utils.searchInformation(utils.root);
//获取最大uidnumber
//int uidnumber = utils.getMaxUid();
//System.out.println("最大uidnumber:"+uidnumber);
utils.close();
}
/**
* @Description:使用非安全方式登录
* @author erek
* @date 2018-07-03
*/
public void init() {
Properties env = new Properties();
String adminName = "cn=administrator,cn=Users,dc=domain,dc=sensetime,dc=com";// username@domain
String adminPassword = "123@abc";// password
String ldapURL = "ldap://10.100.52.237:389";// ip:port
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"
env.put(Context.SECURITY_PRINCIPAL, adminName);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
env.put(Context.PROVIDER_URL, ldapURL);
try {
dc = new InitialLdapContext(env, null);
System.out.println("AD域帐户密码认证成功");
} catch (Exception e) {
System.out.println("AD域帐户密码认证失败");
e.printStackTrace();
}
}
/**
* @Description:使用SSl的方式登录
* @author erek
* @date 2018-07-03
*/
public void certinit() {
Properties env = new Properties();
//cn=administrator,cn=Users,dc=domain,dc=sensetime,dc=com
String adminName = "cn=administrator,cn=Users,dc=domain,dc=sensetime,dc=com";
//String adminName = "cn=erek,ou=people,dc=domain,dc=sensetime,dc=com";
env.put(Context.AUTHORITATIVE, "true");
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
//使用ldaps 登录时候访问安全级别一定要设置为simple,否则修改密码相关失败。
env.put(Context.SECURITY_AUTHENTICATION, "simple");//LDAP访问安全级别:"none","simple","strong"
env.put(Context.SECURITY_PRINCIPAL, USER_NAME);
env.put(Context.SECURITY_CREDENTIALS, USER_PWD);
env.put(Context.PROVIDER_URL, LDAPURL);
env.put(Context.SECURITY_PROTOCOL, "ssl");
//免证书登录属性设置,这个很关键
env.put("java.naming.ldap.factory.socket","org.utils.ad.LTSSSLSocketFactory");
//env.put("com.sun.jndi.ldap.object.disableEndpointIdentification", true);
//System.setProperty("com.sun.jndi.ldap.object.disableEndpointIdentification", true);
//env.put(key, value)
//env.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url");
//env.setProperty(Context.REFERRAL, "ignore");
//以下三项为有证书方式连接
// String keystore = "C:\\Program Files\\Java\\jdk1.8.0_202\\jre\\lib\\security\\cacerts";
// System.setProperty("javax.net.ssl.trustStore", keystore);
// System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
//
// Create connection controls to use
try {
dc = new InitialLdapContext(env, null);
System.out.println("AD域ssl身份认证成功");
} catch (Exception e) {
System.out.println("AD域ssl身份认证失败");
e.printStackTrace();
}
}
/**
* @Description:关闭AD域服务连接
* @author erek
* @date 2018-07-03
*/
public void close() {
if (dc != null) {
try {
dc.close();
System.out.println("AD域服务连接关闭");
} catch (NamingException e) {
System.out.println("NamingException in close():" + e);
}
}
}
/**
* @Description:新增AD域用户
* @author erek
* @date 2018-07-03
*/
public void add(String newUserName) {
try {
String newQuotedPassword = "\"GoodSense@\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
//"unicodePwd: "+newUnicodePassword,
BasicAttribute objclassSet = new BasicAttribute("objectclass");
objclassSet.add("top");
objclassSet.add("person");
objclassSet.add("organizationalPerson");
objclassSet.add("user");
Attributes attrs = new BasicAttributes(true);
//attrs.put("objectClass", "user");
attrs.put(objclassSet);//将objectclass加到属性集合中
attrs.put("samAccountName", newUserName);
attrs.put("userPrincipalName", newUserName + "@sensetime.com");
attrs.put("userAccountControl","512");
attrs.put("unicodePwd",newUnicodePassword);
attrs.put("telephoneNumber","15880888368");
attrs.put("displayName", "显示名称");
attrs.put("description","描述");
attrs.put("mail",newUserName + "@sensetime.com");
attrs.put("givenName","名字");
attrs.put("name","newUserName");
attrs.put("cn", newUserName);
attrs.put("sn", newUserName);
//attrs.put("uidnumber", getMaxUid());
dc.createSubcontext("cn=" + newUserName + "," + root, attrs);
System.out.println("新增AD域用户成功:" + newUserName);
} catch (Exception e) {
e.printStackTrace();
System.out.println("新增AD域用户失败:" + newUserName);
}
}
/**
* @Description:删除AD域用户
* @author erek
* @date 2018-07-03
*/
public void delete(String userName) {
String dn = "cn="+userName+","+ root;
try {
dc.destroySubcontext("cn="+userName+","+ root);
System.out.println("删除AD域用户成功:" + dn);
} catch (Exception e) {
System.out.println("删除AD域用户失败:" + dn);
e.printStackTrace();
}
}
/**
* @Description:重命名AD域用户
* @author erek
* @date 2018-07-03
*/
public boolean renameEntry(String oldDN, String newDN) {
try {
dc.rename(oldDN, newDN);
System.out.println("重命名AD域用户成功");
return true;
} catch (NamingException ne) {
System.out.println("重命名AD域用户失败");
ne.printStackTrace();
return false;
}
}
/**
* @Description:修改AD域用户属性
* @author erek
* @date 2018-07-03
*/
public void updatePerson(String dn) {
Person person = new Person();
person.setCn(dn);
person.setSAMAccountName(person.getCn());
person.setName(person.getCn());
person.setSn("3");
person.setUserAccountControl("66048");
person.setTelephoneNumber("18999999958");
person.setGivenName("33");
person.setDescription("3333");
person.setDisplayName("333");
person.setMail("dn@case.com");
person.setUserPassword("Root.123");
if (person == null || person.getCn() == null
|| person.getCn().length() <= 0) {
return;
}
//修改的属性
List<ModificationItem> mList = new ArrayList<ModificationItem>();
//不能修改
//mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userAccountControl", person.getUserAccountControl())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("sn",person.getSn())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("telephoneNumber", person.getTelephoneNumber())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail", person.getMail())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("givenName", person.getGivenName())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName", person.getDisplayName())));
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("description", person.getDescription())));
if (mList.size() > 0) {
//集合转为数组
ModificationItem[] mArray = new ModificationItem[mList.size()];
for (int i = 0; i < mList.size(); i++) {
mArray[i] = mList.get(i);
}
try {
dc.modifyAttributes("cn="+dn + "," + root, mArray);
System.out.println("修改AD域用户属性成功");
} catch (NamingException e) {
System.err.println("修改AD域用户属性失败");
e.printStackTrace();
}
}
}
public void StringToAscc8(String args) {
ArrayList<String> messageList = new ArrayList<String>();
String text = "abc";
byte[] bytes = text.getBytes();
StringBuilder binary = new StringBuilder();
for (byte b : bytes) {
int val = b;
for (int i = 0; i < 8; i++) {
binary.append((val & 128) == 0 ? 0 : 1);
val <<= 1;
}
binary.append(' ');
}
messageList.add(binary.toString());
System.out.println(Arrays.toString(bytes));
for (String object : messageList) {
System.out.println("'" + text + "' to binary: " + object);
}
// this part below to help you to save 2-bit binary converted in int
// arraylist to store string
ArrayList<String> stringList = new ArrayList<String>();
for (int i = 0; i < text.length(); i++) {
stringList.add(messageList.get(0).split(" ")[i]);
}
// arraylist to store int converted
ArrayList<Integer> intList = new ArrayList<Integer>();
for (String str : stringList) {
for (int i = 0; i < str.length(); i += 2) {
intList.add(Integer.parseInt(str.substring(i, i + 2), 2));
System.out.print(str.substring(i, i + 2) + " ");
}
}
System.out.println();
// nowretrieve int in arraylist to convert in 2-binary if you wont
for (Integer integer : intList) {
System.out.print(integer + " ");
}
}
/**
* @Description:修改AD域用户密码
* @param dn 用户
* @param oldPwd 旧密码
* @param newPwd 新密码
* @author erek
* @date 2019-07-03
*/
public void updatePWD(String dn,String oldPwd,String newPwd) {
Person person = new Person();
person.setCn(dn);
person.setUserPassword(newPwd);
String sOldPassword =oldPwd;
if (person == null || person.getCn() == null
|| person.getCn().length() <= 0) {
return;
}
try {
String oldQuotedPassword = "\"" + sOldPassword + "\"";
byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE");
String newQuotedPassword = "\"" + person.getUserPassword() + "\"";
byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
ModificationItem[] mods = new ModificationItem[2];
//mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword));
mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, new BasicAttribute("unicodePwd", oldUnicodePassword)); //userPassword
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE, new BasicAttribute("unicodePwd", newUnicodePassword));
// mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
// new BasicAttribute("unicodePwd", newUnicodePassword));
//
//dc.bind(name, obj);
dc.modifyAttributes("cn="+dn + "," + root, mods);
//dc.modifyAttributes("cn="+dn + ",ou=people,dc=domain,dc=sensetime,dc=com", mods);
System.out.println("修改密码成功!");
}catch(Exception e) {
e.printStackTrace();
System.out.println("修改密码失败!"+e.toString());
}
}
/**
* @Description:修改AD域用户属性
* @author erek
* @date 2018-07-03
*/
public void enablePerson(String dn) {
/**
Person person = new Person();
person.setCn("testzhu");
person.setUserAccountControl("66048");
if (person == null || person.getCn() == null
|| person.getCn().length() <= 0) {
return;
}
try {
ModificationItem[] mods = new ModificationItem[1];
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userAccountControl", person.getUserAccountControl()));
dc.modifyAttributes("cn="+dn + "," + root, mods);
System.out.println("启用用户成功!");
}catch(Exception e) {
e.printStackTrace();
}
*/
}
/**
* @Description:搜索指定节点下的所有AD域用户
* @author erek
* @date 2018-07-03
*/
public void searchInformation(String searchBase) {
//要获取的对象属性
String[] attributeNames = { "memberOf", "uidNumber","name","objectClass"};
try {
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "objectClass=user";
String returnedAtts[] = { "memberOf" };
searchCtls.setReturningAttributes(returnedAtts);
NamingEnumeration<?> answer = dc.search(searchBase, searchFilter, searchCtls);
//NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
//SearchResult sr = (SearchResult) answer.next();
//System.out.println(sr.getName());
NameClassPair ncp = (NameClassPair) answer.next();
String ncpName = ncp.getName();
// 对特殊字符的DN跳过
//if ((ncpName + "," + searchBase).indexOf("\"") != -1 || (ncpName + "," + searchBase).indexOf("/") != -1) {continue;}
Attributes atts = dc.getAttributes(ncpName + "," + searchBase, attributeNames);
//获取对象属性
Attribute uidnumber = atts.get("uidNumber");
if(uidnumber!=null) {
String value = (String) uidnumber.get();
System.out.println(ncpName+"|"+value+"uidNumber:"+uidnumber.toString());
}
/**
Attribute objectClassAuttribute = atts.get("objectClass");
if(objectClassAuttribute != null) {
if (objectClassAuttribute.toString().indexOf("user") != -1) {
//获取用户是user
System.out.println(atts+ncpName + "," + searchBase);
}
}
*/
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @Description:指定搜索节点搜索指定域用户
* @author erek
* @date 2018-07-03
*/
public SearchResult searchByUserName(String searchBase, String userName) {
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "cn=" + userName;
String returnedAtts[] = { "memberOf" }; //定制返回属性
searchCtls.setReturningAttributes(returnedAtts); //设置返回属性集
try {
NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
return answer.next();
} catch (Exception e) {
System.err.println("指定搜索节点搜索指定域用户失败");
e.printStackTrace();
}
return null;
}
/**
* @Description:指定搜索节点搜索指定域用户
* @author erek
* @throws Exception
* @date 2018-07-03
*/
public void searchByUserNameUidNumber(String searchBase, String userName) throws Exception {
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "cn=" + userName;
String returnedAtts[] = { "memberOf" }; //定制返回属性
searchCtls.setReturningAttributes(returnedAtts); //设置返回属性集
String[] attributeNames = { "memberOf", "uidNumber","name","objectClass"};
/*
* try { NamingEnumeration<SearchResult> answer = dc.search(searchBase,
* searchFilter, searchCtls);
*
* return answer.next(); } catch (Exception e) {
* System.err.println("指定搜索节点搜索指定域用户失败"); e.printStackTrace(); }
*/
NamingEnumeration<?> answer = dc.search(searchBase, searchFilter, searchCtls);
//NamingEnumeration<SearchResult> answer = dc.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
//SearchResult sr = (SearchResult) answer.next();
//System.out.println(sr.getName());
NameClassPair ncp = (NameClassPair) answer.next();
String ncpName = ncp.getName();
// 对特殊字符的DN跳过
//if ((ncpName + "," + searchBase).indexOf("\"") != -1 || (ncpName + "," + searchBase).indexOf("/") != -1) {continue;}
Attributes atts = dc.getAttributes(ncpName + "," + searchBase, attributeNames);
//获取对象属性
Attribute uidnumber = atts.get("uidNumber");
/**
if(uidnumber!=null) {
String value = (String) uidnumber.get();
System.out.println(ncpName+" "+uidnumber.toString());
}
*/
if(uidnumber!=null) {
String value = (String) uidnumber.get();
//System.out.println(value+"uidNumber:"+uidnumber.toString());
int uidn = Integer.valueOf(value);
System.out.println(ncpName+" "+uidn);
}
/**
Attribute objectClassAuttribute = atts.get("objectClass");
if(objectClassAuttribute != null) {
if (objectClassAuttribute.toString().indexOf("user") != -1) {
//获取用户是user
System.out.println(atts+ncpName + "," + searchBase);
}
}
*/
}
}
public int getMaxUid() {
int max_uid = 10000;
int count = 0;
String searchBase = "ou=robots,dc=domain,dc=sensetime,dc=com";
String searchPeopleBase = "ou=people,dc=domain,dc=sensetime,dc=com";
//要获取的对象属性
String[] attributeNames = {"uidNumber"};
try {
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
String searchFilter = "cn=*";
String returnedAtts[] = { "memberOf" };
searchCtls.setReturningAttributes(returnedAtts);
//1、先查询robots 最大uidNumber
NamingEnumeration<?> answer = dc.search(searchBase, searchFilter, null);
while (answer.hasMoreElements()) {
count++;
System.out.println("searchBase:"+count);
//SearchResult sr = (SearchResult) answer.next();
//System.out.println(sr.getName());
NameClassPair ncp = (NameClassPair) answer.next();
String ncpName = ncp.getName();
// 对特殊字符的DN跳过
//if ((ncpName + "," + searchBase).indexOf("\"") != -1 || (ncpName + "," + searchBase).indexOf("/") != -1) {continue;}
Attributes atts = dc.getAttributes(ncpName + "," + searchBase, attributeNames);
//获取对象属性
Attribute uidnumber = atts.get("uidNumber");
if(uidnumber!=null) {
String value = (String) uidnumber.get();
//System.out.println(value+"uidNumber:"+uidnumber.toString());
int uidn = Integer.valueOf(value);
if(uidn >= 22145) {
System.out.println(uidn);
}
if(uidn > max_uid) {
max_uid = uidn;
}
}
}
//2、查询people 最大uidNumber
NamingEnumeration<?> answer1 = dc.search(searchPeopleBase, searchFilter, null);
while (answer1.hasMoreElements()) {
count++;
NameClassPair ncp = (NameClassPair) answer1.next();
String ncpName = ncp.getName();
// 对特殊字符的DN跳过
//if ((ncpName + "," + searchBase).indexOf("\"") != -1 || (ncpName + "," + searchBase).indexOf("/") != -1) {continue;}
Attributes atts = dc.getAttributes(ncpName + "," + searchPeopleBase, attributeNames);
//获取对象属性
Attribute uidnumber = atts.get("uidNumber");
if(uidnumber!=null) {
String value = (String) uidnumber.get();
//System.out.println(value+"uidNumber:"+uidnumber.toString());
int uidn = Integer.valueOf(value);
if(uidn >= 22145) {
System.out.println(uidn);
}
if(uidn > max_uid) {
max_uid = uidn;
}
}
}
System.out.println("共查询账号数:"+count);
} catch (Exception e) {
e.printStackTrace();
}
return max_uid+1;
}
}