JAVA修改AD账号密码
今天正好做了这块,拿出来分享。以前在网上找到的都无法实现。代码内容不太规范,只是一个测试的用例
有什么问题可以联系我QQ:305493325。
一、生成JKS文件
1、下载AD域的根证书,访问https://10.1.0.10:636 (需要IE6导出根证书)。只需要根证书;
2、生成JKS。使用KEYTOOL工具生成
新建KeyStore
(图片内容参考附件)
选择KeyStore的类型
(图片内容参考附件)
点击保存后,输入KeyStore的密码
(图片内容参考附件)
导入根证书
(图片内容参考附件)
下一步后输入证书的别名
(图片内容参考附件)
成功后,点击保存,JKS生成完成
(图片内容参考附件)
二、编写代码
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
importjavax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
importjavax.naming.directory.InitialDirContext;
importjavax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
public class AdOpration {
private String ldapUser = "";
private String ldapPwd = "";
private String ldapUrl = "";
private String baseDN = "";
private DirContext dc = null;
public AdOpration(String baseDN,String ldapUser ,String ldapPwd ,StringldapUrl) {
this.baseDN = baseDN;
this.ldapUser = ldapUser;
this.ldapPwd = ldapPwd;
this.ldapUrl = ldapUrl;
this.dc = this.getADContext();
}
/**得到连接的上下文 */
public DirContext getADContext(){
Hashtable<Object, Object> env = new Hashtable<Object,Object>();
String trustStore = "c:/test-ad-key.jks"; //JKS存放的位置
String trustStorePwd = "123456"; // JKS密码
System.setProperty("javax.net.ssl.trustStore", trustStore);
System.setProperty("javax.net.ssl.trustStorePassword",trustStorePwd);
env.put(Context.SECURITY_PROTOCOL, "ssl");
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUser);
env.put(Context.SECURITY_CREDENTIALS, ldapPwd);
DirContext ctx=null;
try {
env.put(Context.PROVIDER_URL, ldapUrl);
ctx = new InitialDirContext(env);
}catch (NamingException e) {
e.printStackTrace();
}
return ctx;
}
/**
* 查询ldapDN
*/
public String getAccountDNByName(String username) {
String accountDN = "";
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
String filter = "(&(objectClass=user)(samaccountname=" +username + "))";
NamingEnumeration en = dc.search(baseDN, filter,constraints);
System.out.println("filter="+filter);
while (en.hasMoreElements()) {
SearchResult rs=(SearchResult)en.nextElement();
accountDN=rs.getName()+","+baseDN;
}
}catch(Exception e) {
}
return accountDN;
}
/**
* 关闭Ldap连接*/
public void closeLdap() {
try {
this.dc.close();
}catch (NamingException e) {
}
}
/**修改AD密码*/
public boolean changePwd(String userName,String pwd){
boolean flag = false;
ModificationItem[] mods = new ModificationItem[1];
String newQuotedPassword = "\"" + pwd +"\"";
try {
byte[] newUnicodePassword =newQuotedPassword.getBytes("UTF-16LE");
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
new BasicAttribute("unicodePwd", newUnicodePassword));
this.dc.modifyAttributes(userName, mods);
flag = true;
}catch (Exception e) {
flag = false;
}
return flag;
}
public static void main(String arg[]){
String ldapUser = "siamtest@contoso.org"; //一定需要管理员的权限
String ldapPwd = "abcd.1234";
String ldapUrl = "ldaps://10.1.0.10:636"; // 连接的URL,必须使用ldaps
String username = "dgcaiym.gdsy"; //被修改人员的AD账号
String userPwd = "P@ssw0rd";
String baseDN = "DC=contoso,DC=org"; // AD组织的baseDN
AdOpration adOperation = new AdOpration(baseDN,ldapUser,ldapPwd,ldapUrl);
String dn = adOperation.getAccountDNByName(username);
System.out.println("==========User DN==========="+dn);
boolean flag = adOperation.changePwd(dn, userPwd);
System.out.println("==========ChangePassword==========="+flag);
adOperation.closeLdap();
}
}
注意:
1、 首先确保连接上,能够查询AD账号的DN后,表示JKS都没有问题;
2、 报“problem5003 (WILL_NOT_PERFORM)”错误时,表示当前的密码不符合AD密码策略;
3、 测试发现,当账号挂在OU=组织机构,DC=contoso,DC=org下时,修改成功但实际没有修改成功,必须在OU=组织机构,DC=contoso,DC=org以下的节点下。