此代码是上一篇文章的补充,通过上一篇文章配置好ssl证书后,直接复制此代码就可以验证了。
代码如下:
package LdapOperUtil;
import javax.naming.Context;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* ldap方式 对AD域用户进行增删改查
*/
public class ADUtil {
// 常量定义
// AD域的根节点的DC(域名)
final static String root = "DC=example,DC=bdc";
// 管理员用户名
final static String adminName = "example\\Administrator";
// 管理员用户密码
final static String adminPassWord = "test.123456";
// jdk的ssl证书文件路径
final static String javaSsLFile = "C:\\Workspace\\tool\\jdk\\java1.8\\jdk1.8\\jre\\lib\\security\\cacerts";
// ad域ip地址
final static String adIP = "192.168.253.11";
// ad域连接ssl端口号
final static int adSsLPort = 636;
// ad域连接普通端口号
final static int adNormalPort = 389;
// 保存当前类对象
private static ADUtil ldapOperUtil;
private static DirContext ldapContext = null;
private static LdapContext ctx;
// 创建当前类对象时,自动创建连接对象,并对ldapContext和ctx赋值
private ADUtil() {// 默认连接636端口
getConnectSSL(adminName, adminPassWord, javaSsLFile, adIP, adSsLPort);
}
/**
* @param connSelect,创建对象时传入参数的连接选择,参数为normal和ssl两种
* @throws Exception
*/
private ADUtil(String connSelect) throws Exception {// 创建对象时传入参数的连接选择,参数为normal和ssl两种
if (connSelect.trim().equals(" ") || connSelect == null
|| !(connSelect.trim().equals("normal"))
|| !(connSelect.trim().equals("ssl"))) {
throw new Exception("连接参数为空,请输入有效参数:normal | ssl");
} else if (connSelect.trim().equals("normal")) {
getConnectNormal(adIP, adNormalPort, adminName, adminPassWord);
} else if (connSelect.trim().equals("ssl")) {
getConnectSSL(adminName, adminPassWord, javaSsLFile, adIP,
adSsLPort);
}
}
// 懒汉模式的单例模式
public static ADUtil getNewInstance() {
if (ldapOperUtil == null) {
ldapOperUtil = new ADUtil();
}
return ldapOperUtil;
}
/**
* 1 连接AD域,根据用户的登录名来进行连接,和显示的名称、用户姓、用户名无关 此方式是389普通方式连接
* @param adIp ad域地址
* @param port ad域连接端口号
* @param adminName 管理员账户名
* @param adminPassword 管理员账户密码
* @return
*/
public static LdapContext getConnectNormal(String adIp, int port,
String adminName, String adminPassword) {
boolean isReady = true;
Hashtable<String, String> env = new Hashtable<>();
// 引用ldap工厂模式创建对象,固定写法
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
// 连接ad的url,格式为:ldap://adip:port,port可以是389,636,389是普通模式,可以对用户增删改查操作;636是ssl方式,可以进行用户密码修改等操作
String ldapURL = "ldap://" + adIp + ":" + port;// 连接iP与端口号
env.put(Context.PROVIDER_URL, ldapURL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");// 输出网络认证实例,一般都是simple方式
// 用户名(管理员用户) ,格式是:域名\\用户名
env.put(Context.SECURITY_PRINCIPAL, adminName);// 用户名(管理员用户)
env.put(Context.SECURITY_CREDENTIALS, adminPassword);// 用户的密码
try {
ldapContext = new InitialDirContext(env);
ctx = new InitialLdapContext(env, null);
System.out.println(adminName.trim().split("\\\\")[1].trim()
+ "连接AD域成功");
} catch (Exception e) {
isReady = false;
e.printStackTrace();
System.err.println(adminName.trim().split("\\\\")[1].trim()
+ "连接AD域失败");
} finally {
if (isReady == true) {
return ctx;
}
return null;
}
}
/** 此方式是通过ssL方式连接
* @param userName 用户名
* @param passWord 密码
* @param keyStore ssl认证文件位置
* @param LDAP_URL ad域IP地址
* @param port 连接端口号
* @return
*/
public static LdapContext getConnectSSL(String userName, String passWord,
String keyStore, String LDAP_URL, int port) {
Hashtable env = new Hashtable();
// 加载导入jdk的域证书
System.setProperty("javax.net.ssl.trustStore", keyStore);
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");// ssl认证的密码
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");// 固定写法
env.put(Context.SECURITY_PROTOCOL, "ssl");
// 连接认证服务器
env.put(Context.PROVIDER_URL, "ldaps://" + LDAP_URL + ":" + port);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, userName);
env.put(Context.SECURITY_CREDENTIALS, passWord);
try {
ldapContext = new InitialDirContext(env);
ctx = new InitialLdapContext(env, null);
System.out.println(userName.trim().split("\\\\")[1].trim()
+ "认证成功!!!");
return ctx;
} catch (javax.naming.AuthenticationException e) {
System.out.println("认证失败:" + e.getMessage());
} catch (Exception e) {
System.out.println("认证出错:" + e.getMessage());
}
return null;
}
/**
* 添加组织机构
* @param ouDN 要添加的组织机构全路径,如: CN=Users,DC=example,DC=bdc
* @return
* @throws NamingException
*/
public static boolean addOU(String ouDN) throws NamingException {
try {
Attributes attrs = new BasicAttributes(true);
attrs.put("objectClass", "organizationalUnit");
ctx.createSubcontext(ouDN, attrs);
return true;
} catch (Exception e) {
e.printStackTrace();
} finally {
if (ctx != null) {
ctx.close();
ctx = null;
}
}
return false;
}
/**
* 遍历AD域指定节点所有用户
* @param baseDN 要查询的组织机构全路径,如: CN=Users,DC=example,DC=bdc
* @return List<String>
* @throws NamingException
*/
public static List<String> getUserInfo(String baseDN)
throws NamingException {
SearchControls searchCtls = new SearchControls(); // 设置搜索范围
String returnedAtts[] = { "distinguishedName", "sAMAccountName",
"userPrincipalName" };
searchCtls.setReturningAttributes(returnedAtts); // 设置指定返回的字段,不设置则默认返回全部
List<String> userMessageList = new ArrayList();// 设置一个集合,用来保存用户信息
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);// 全部参数是OBJECT_SCOPE,ONELEVEL_SCOPE
// 注意OU和DC的先后顺序,cn,ou,dc 分别:用户,组,域
NamingEnumeration results = ldapContext.search(baseDN,
"objectClass=User", searchCtls);
while (results.hasMoreElements()) {
SearchResult sr = (SearchResult) results.next();// 返回查到用户的详细信息
Attributes attributes = sr.getAttributes();// 得到所需的用户信息组
Attribute userPrincipalName = attributes.get("userPrincipalName");// 存在null项的话,直接使用toString()会报错
String testString = "";
if (userPrincipalName == null) {
testString = "null:null";
} else {
testString = userPrincipalName.toString();
}
String[] userNameArray = attributes.get("distinguishedName")
.toString().split("\\:");// 分隔字符串,得到需要信息
String[] userPrincipalNameArray = testString.split("\\:");
String[] sAMAccountNameArray = attributes.get("sAMAccountName")
.toString().split("\\:");
String userMessage = "用户名:" + userNameArray[1] + ",票据名:"
+ userPrincipalNameArray[1] + ",对应登录名:"
+ sAMAccountNameArray[1];
userMessageList.add(userMessage);// 将返回的信息存到定义的用户list中
}
System.out.println("遍历成功");
return userMessageList;
}
/**
* 添加一个用户,此方式只适合通过636端口添加用户,通过389添加的用户无法设置密码
* @param newUserName 添加的用户名
* @param password 添加用户的密码
* @param userPrincipalName 用户所持有的服务票据
* @param rootDN 要添加到ad域的节点信息
*/
public static void addUserBySSL(String newUserName, String password,
String userPrincipalName, String rootDN) {
try {
BasicAttributes attrs = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectClass");
objclassSet.add("person");
objclassSet.add("top");
objclassSet.add("user");
attrs.put(objclassSet);
// 设置姓
attrs.put("sn",
newUserName.substring(0, newUserName.trim().length() / 2));
attrs.put("givenName",
newUserName.substring(newUserName.trim().length() / 2));// 设置名
attrs.put("CN", newUserName);// 用户名
attrs.put("displayName", newUserName);// 显示名称
attrs.put("description", "集群kerberos服务用户");// 用户信息描述
attrs.put("userPrincipalName", userPrincipalName);// 和用户绑定的服务票据名
attrs.put("sAMAccountName", newUserName); // 设置登录名
attrs.put("msDS-SupportedEncryptionTypes", "0");
int UF_ACCOUNTDISABLE = 0x0002;
int UF_PASSWD_NOTREQD = 0x0020;
int UF_PASSWD_CANT_CHANGE = 0x0040;
int UF_NORMAL_ACCOUNT = 0x0200;
int UF_DONT_EXPIRE_PASSWD = 0x10000;
int UF_PASSWORD_EXPIRED = 0x800000;
// 密码永不过期
attrs.put(
"userAccountControl",
Integer.toString(UF_DONT_EXPIRE_PASSWD
+ UF_PASSWD_CANT_CHANGE + UF_PASSWD_NOTREQD));
System.out.println("正在处理的用户为:" + newUserName);
Context result = ldapContext.createSubcontext("CN=" + newUserName
+ "," + rootDN, attrs);// 添加用户
updateAdPwdByReplace("CN=" + newUserName + "," + rootDN, password);// 用户密码初始化
System.out.println("用户" + newUserName + "添加成功");
} catch (NameAlreadyBoundException e) {
System.err.println("用户" + newUserName + "已经存在,请修改名字!");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 添加一个用户,此方式通过389添加用户,无法设置密码,需要通过636端口连接后重置密码
* @param newUserName 添加的用户名
* @param password 添加用户的密码
* @param userPrincipalName 用户所持有的服务票据
* @param rootDN 要添加到ad域的节点信息
*/
public static void addUserByNormal(String newUserName,
String userPrincipalName, String rootDN) {
try {
BasicAttributes attrs = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectClass");
objclassSet.add("person");
objclassSet.add("top");
objclassSet.add("user");
attrs.put(objclassSet);
// 设置姓
attrs.put("sn",
newUserName.substring(0, newUserName.trim().length() / 2));
attrs.put("givenName",
newUserName.substring(newUserName.trim().length() / 2));// 设置名
attrs.put("CN", newUserName);// 用户名
attrs.put("displayName", newUserName);// 显示名称
attrs.put("description", "集群kerberos服务用户");// 用户信息描述
attrs.put("userPrincipalName", userPrincipalName);// 和用户绑定的服务票据名
attrs.put("sAMAccountName", newUserName); // 设置登录名
attrs.put("msDS-SupportedEncryptionTypes", "0");
int UF_ACCOUNTDISABLE = 0x0002;
int UF_PASSWD_NOTREQD = 0x0020;
int UF_PASSWD_CANT_CHANGE = 0x0040;
int UF_NORMAL_ACCOUNT = 0x0200;
int UF_DONT_EXPIRE_PASSWD = 0x10000;
int UF_PASSWORD_EXPIRED = 0x800000;
// 密码永不过期
attrs.put(
"userAccountControl",
Integer.toString(UF_DONT_EXPIRE_PASSWD
+ UF_PASSWD_CANT_CHANGE + UF_PASSWD_NOTREQD));
System.out.println("正在处理的用户为:" + newUserName);
Context result = ldapContext.createSubcontext("CN=" + newUserName
+ "," + rootDN, attrs);// 添加用户
System.out.println("用户" + newUserName + "添加成功");
} catch (NameAlreadyBoundException e) {
System.err.println("用户" + newUserName + "已经存在,请修改名字!");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 删除一个用户
* @param username 用户名
* @param baseDN 用户所在节点
*/
public static void delete(String username, String baseDN) {
try {
if (getUserByName(username, baseDN).trim().equals("用户不存在,请检查!!!")) {// 先判断是否存在此用户,有在删除,没有就提示不存在此用户
System.out.println("用户" + username + "不存在,请检查!!!");
} else {
ldapContext.destroySubcontext("CN=" + username + "," + baseDN);
System.out.println("用户" + username + "删除成功");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/** 查询ldapDN,查看用户是根据用户的显示名来查询的
* @param username 用户名
* @param baseDN 用户所在ad域节点
* @return
*/
public static String getUserByName(String username, String baseDN) {
String accountDN = " ";
try {
SearchControls constraints = new SearchControls();// 建立搜索
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);// 设置搜索选项
// String filter = "(&(objectClass=user)(samaccountname=" +
// username+ "))";//设置匹配项筛选,根据登录名搜索
String filter = "(&(objectCategory=person)(objectClass=user)(cn="
+ username + "))";// 设置匹配项筛选,根据用户名搜索
NamingEnumeration en = ldapContext.search(baseDN, filter,
constraints);
if (en.hasMoreElements() == false) {// 判断是否匹配到结果
return accountDN = "用户不存在,请检查!!!";
} else {
while (en.hasMoreElements()) {
SearchResult rs = (SearchResult) en.nextElement();
accountDN = "用户名:" + rs.getName() + "," + baseDN;// 查询到结果,返回用户的所在节点详细信息
}
}
} catch (Exception e) {
e.printStackTrace();
}
return accountDN;
}
/** 得到指定用户所持有的票据信息
* @param username 用户名
* @param baseDN 用户所在ad域节点
* @return
*/
public static String getUserPrincipalName(String username, String baseDN) {
String userPrincipal = " ";
try {
SearchControls constraints = new SearchControls();// 建立搜索
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);// 设置搜索选项
// String filter = "(&(objectClass=user)(samaccountname=" +
// username+ "))";//设置匹配项筛选,根据登录名搜索
String filter = "(&(objectCategory=person)(objectClass=user)(cn="
+ username + "))";// 设置匹配项筛选,根据用户名搜索
NamingEnumeration en = ldapContext.search(baseDN, filter,
constraints);
if (en.hasMoreElements() == false) {// 判断是否匹配到结果,没有结果就返回空值
return userPrincipal = "null:null";
} else {
while (en.hasMoreElements()) {
SearchResult rs = (SearchResult) en.nextElement();
Attributes attributes = rs.getAttributes();// 得到所需的用户信息组
Attribute userPrincipalName = attributes
.get("userPrincipalName");// 得到用户所持票据名,存在null项的话,直接使用toString()会报错
String testString = "";
if (userPrincipalName == null) {
testString = "null:null";
} else {
testString = userPrincipalName.toString();
}
userPrincipal = (testString.trim().split("\\:"))[1].trim();// 通过分割字符串得到所要的票据名,去掉说明信息
}
}
} catch (Exception e) {
e.printStackTrace();
}
return userPrincipal;
}
/** 修改用户名
*
* @param userName 要修改的用户名
* @param newName 修改之后的用户名
* @param userDN 用户所在位置
*/
public static void renameUser(String userName, String newName, String userDN) {
try {
if (getUserByName(userName, userDN).trim().equals("用户不存在,请检查!!!")) {// 先判断用户是否存在
System.err.println("用户名不存在,请重新输入!!!");
} else {
ctx.rename("CN=" + userName + "," + userDN, "CN=" + newName
+ "," + userDN);
System.out.println("用户名修改成功!!!");
updateOnePersonByCn(newName, userDN);// 用户名修改后,同步用户姓,名,登录名属性值
}
} catch (NamingException ne) {
ne.printStackTrace();
System.err.println("用户名修改失败!!!");
}
}
/**
* 重置/修改密码
* 通过直接替换密码字段里面的值
*
* @param userDN 用户所在位置全路径
* @param passWord 密码
* @return
*/
public static Boolean updateAdPwdByReplace(String userDN, String passWord) {
ModificationItem[] mods = new ModificationItem[2];
try {
passWord = "\"" + passWord + "\"";
byte[] newpasswordBytes = passWord.getBytes("UTF-16LE");
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("unicodePwd", newpasswordBytes));
mods[1] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("pwdLastSet", "0"));
ldapContext.modifyAttributes(userDN, mods);
System.out.println("用户" + userDN + "重置密码成功");
return true;
} catch (Exception e) {
System.err.println("用户" + userDN + "重置密码失败" + e.getMessage());
return false;
}
}
/**
* 修改用户属性信息
* @param adUser 要修改的用户对象
* @param BaseDN 用户所在位置
* @throws NamingException
*/
public static void updateOnePersonAll(AdUser adUser, String BaseDN)
throws NamingException {
if (adUser == null || adUser.getCn() == null
|| adUser.getCn().length() <= 0) {
return;
}
List<ModificationItem> mList = new ArrayList<ModificationItem>(); // 构造要修改对象的属性组
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("displayName", adUser.getDisplayName()))); // 修改用户显示名
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("sn", adUser.getSn()))); // 修改用户姓
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("givenName", adUser.getGivenName()))); // 修改用户名
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("userPrincipalName", adUser
.getUserPrincipalName()))); // 修改用户服务票据名
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("description", adUser.getDescription()))); // 修改用户描述信息
mList.add(new ModificationItem(
DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("sAMAccountName", adUser.getSAMAccountName()))); // 修改用户登录名
if (mList.size() > 0) {
ModificationItem[] mArray = new ModificationItem[mList.size()];
for (int i = 0; i < mList.size(); i++) {
mArray[i] = mList.get(i);
}
ldapContext.modifyAttributes(getUserByName(adUser.getCn(), BaseDN)
.trim().split("\\:")[1], mArray);// 参数为:用户详细位置,修改的用户属性组
System.out.println("用户" + adUser.getCn() + "属性修改成功");
}
}
/**
* 同步用户属性信息 ,只修改用户姓,名和登录名
* @param username 要修改的用户名
* @param BaseDN 用户所在位置
* @throws NamingException
*/
public static void updateOnePersonByCn(String username, String BaseDN)
throws NamingException {
AdUser aduser = new AdUser(username);
if (aduser == null || aduser.getCn() == null
|| aduser.getCn().length() <= 0) {
System.out.println("用户名不能为空");
return;
}
List<ModificationItem> mList = new ArrayList<ModificationItem>(); // 构造要修改对象的属性组
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("displayName", aduser.getDisplayName()))); // 修改用户显示名
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("sn", aduser.getSn()))); // 修改用户姓
mList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("givenName", aduser.getGivenName()))); // 修改用户名
mList.add(new ModificationItem(
DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("sAMAccountName", aduser.getSAMAccountName()))); // 修改用户登录名
if (mList.size() > 0) {
ModificationItem[] mArray = new ModificationItem[mList.size()];
for (int i = 0; i < mList.size(); i++) {
mArray[i] = mList.get(i);
}
ldapContext.modifyAttributes(getUserByName(aduser.getCn(), BaseDN)
.trim().split("\\:")[1], mArray);// 参数为:用户详细位置,修改的用户属性组
System.out.println("用户" + username + "属性修改成功");
}
}
public static void main(String[] args) throws Exception {
ADUtil ldap = new ADUtil();
AdUser adUser = new AdUser("testAdd112",
"testupdate/testAdd11@example.bdc", "测试修改用户信息方法");
//测试修改用户属性
// ldap.updateOnePersonAll(adUser,"CN=Users,DC=example,DC=bdc");
//测试修改用户姓,名,登录名
// ldap.updateOnePersonByCn("testAdd112","CN=Users,DC=example,DC=bdc");
//测试添加组织
// System.out.println(ldap.addOU("ou=testadd1,dc=example,dc=bdc"));
//测试通过389端口连接
// ldap.getConnectNormal("192.168.253.11",389,"example\\testAdd112","test@1q2w3e");
//测试修改用户名
ldap.renameUser("testAdd113", "testAdd114",
"CN=Users,DC=example,DC=bdc");
// 测试获取用户全路径
// System.out.println(ldap.getUserPrincipalName("testAdd","CN=Users,DC=example,DC=bdc"));
//测试获取用户票据名
// String dn = ldap.getUserPrincipalName("testuser",
// "CN=Users,DC=example,DC=bdc");
// System.out.println(dn);
// 删除一个用户
// ldap.delete("testAdd112","CN=Users,"+ldap.root.toString());
// 添加一个用户
// ldap.add("testAdd113","test@1q2w3e","testAdd113/test111@example.bdc","CN=Users,DC=example,DC=bdc");
//测试修改用户密码
// ldap.updateAdPwdByReplace("CN=testAdd112,CN=Users,DC=example,DC=bdc",
// "test@1q2w3e");
//测试遍历指定节点下所有用户
List<String> list = ldap.getUserInfo("CN=Users,DC=example,DC=bdc");
for (Object s : list) {
System.out.println(s);
}
}
}
/**
* 用于修改用户属性所建的实体类,只添加了关注的属性
*
*/
class AdUser {
private String Cn;// AD域中的用户名
private String Sn;// 用户姓
private String GivenName;// 用户名
private String DisplayName;// 显示名称
private String UserPrincipalName;// 用户服务票据名
private String Description;// 用户信息描述
private String SAMAccountName;// 用户登录名
public AdUser() {
super();
}
public AdUser(String cn) {
super();
Cn = cn;
Sn = cn.substring(0, cn.trim().length() / 2);
GivenName = cn.substring(cn.trim().length() / 2);
DisplayName = cn;
SAMAccountName = cn;
}
public AdUser(String cn, String userPrincipalName, String description) {
super();
Cn = cn;
Sn = cn.substring(0, cn.trim().length() / 2);
GivenName = cn.substring(cn.trim().length() / 2);
DisplayName = cn;
UserPrincipalName = userPrincipalName;
Description = description;
SAMAccountName = cn;
}
public String getCn() {
return Cn;
}
public void setCn(String cn) {
Cn = cn;
}
public String getSn() {
return Sn;
}
public void setSn(String sn) {
Sn = sn;
}
public String getGivenName() {
return GivenName;
}
public void setGivenName(String givenName) {
GivenName = givenName;
}
public String getDisplayName() {
return DisplayName;
}
public void setDisplayName(String displayName) {
DisplayName = displayName;
}
public String getUserPrincipalName() {
return UserPrincipalName;
}
public void setUserPrincipalName(String userPrincipalName) {
UserPrincipalName = userPrincipalName;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public String getSAMAccountName() {
return SAMAccountName;
}
public void setSAMAccountName(String sAMAccountName) {
SAMAccountName = sAMAccountName;
}
}