java ad域修改密码_JAVA修改AD域密码_免证书认证

本文介绍了一种不使用TrustStore连接AD域并修改用户密码的方法。通过设置特定环境变量,如`java.naming.ldap.factory.socket`,使用自定义的`DummySSLSocketFactory`来实现SSL连接,从而避免了SSL握手失败的问题。提供了完整的Java代码示例,包括用户认证、查找用户信息、获取用户DN、解锁账号、重置密码等操作。
摘要由CSDN通过智能技术生成

更改用户账户密码,必须要使用ssl方式登录到AD。

网上大部分教程使用TrustStore的方式连接,

Hashtable env = newHashtable();

System.setProperty("javax.net.ssl.trustStore", KEYSTORE);

System.setProperty("javax.net.ssl.trustStorePassword", KEYSTORE_PWD);

env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");

env.put(Context.SECURITY_AUTHENTICATION,"simple");

env.put(Context.SECURITY_PRINCIPAL, ADMIN_NAME);

env.put(Context.SECURITY_CREDENTIALS, ADMIN_PASSWORD);

env.put(Context.SECURITY_PROTOCOL,"ssl");

env.put(Context.PROVIDER_URL, LDAP_SSL_URL);try{

ctx= new InitialLdapContext(env, null);//new InitialDirContext(HashEnv);//初始化上下文

} catch(AuthenticationException e) {

System.out.println("身份验证失败!"+e.toString());

e.printStackTrace();

}catch(CommunicationException e) {

System.out.println("AD域连接失败!"+e.toString());

e.printStackTrace();

}catch(Exception e) {

System.out.println("身份验证未知异常!"+e.toString());

e.printStackTrace();

}finally{returnctx;

}

最后ssl连接失败,报如下错误:javax.naming.CommunicationException: simple bind failed: xxxx:636 [Root exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target]。

也有部分教程提到了绕过ssl的方式,但是都只有部分代码,直到遇到了这段代码

完整代码如下:

packageorg.util.ad;importjavax.naming.Context;importjavax.naming.NamingEnumeration;importjavax.naming.NamingException;import javax.naming.directory.*;importjavax.naming.ldap.Control;importjavax.naming.ldap.InitialLdapContext;importjavax.naming.ldap.LdapContext;importjavax.naming.ldap.SortControl;importjava.io.UnsupportedEncodingException;importjava.util.Calendar;importjava.util.Date;importjava.util.Hashtable;public classLdapSSLUtil {private final static String adminName = "xxx";private final static String adminPassword = "xxxx";private final String ldapURL = "LDAPS://xxx.xxx.xxx:636"; //注意,必须使用域名加636端口

private final String factory = "com.sun.jndi.ldap.LdapCtxFactory";private final String BASEN = "OU=xx,DC=xx,DC=xx";private LdapContext ctx = null;private final Control[] sortConnCtls = new SortControl[1];/*** 用户认证

*

*@paramuserName

*@parampassword*/

public voidldap_connect(String userName, String password) {

Hashtable env = new Hashtable();

env.put(Context.INITIAL_CONTEXT_FACTORY, factory);

env.put(Context.SECURITY_AUTHENTICATION,"simple");

env.put(Context.SECURITY_PRINCIPAL, userName);

env.put(Context.SECURITY_CREDENTIALS, password);

env.put(Context.PROVIDER_URL, ldapURL);

env.put(Context.SECURITY_PROTOCOL,"ssl");

env.put("java.naming.ldap.factory.socket", "org.util.ad.DummySSLSocketFactory");try{//初始化ldapcontext,方式1//ctx = new InitialLdapContext(env, null);//方式2

sortConnCtls[0] = new SortControl("sAMAccountName", Control.CRITICAL);

ctx= newInitialLdapContext(env, sortConnCtls);

System.out.println("认证成功");

}catch(Exception e) {

System.out.println("认证失败");

e.printStackTrace();

}

}//关闭连接

public voidclose_connect() {try{if (ctx != null) {

ctx.close();

}

}catch(NamingException e) {

e.printStackTrace();

}

}/*** 查找用户信息

*

*@paramcn

*@return

*/

publicAttributes getUser(String cn) {

Attributes attrs= null;

SearchControls contro= newSearchControls();

contro.setSearchScope(SearchControls.SUBTREE_SCOPE);try{//有的企业员工的dn不是有cn开头的,而是由uid开头的,这个因企业而异//使用cn,若存在重名用户,则返回的是最后一个员工,存在bug//NamingEnumeration en = ctx.search(BASEN, "cn=" + cn, contro);//使用sAMAccountName,避免重名,比如存在四个张伟

NamingEnumeration en = ctx.search(BASEN, "sAMAccountName=" +cn, contro);if (en == null || !en.hasMoreElements()) {

System.out.println("未找到该用户:" +cn);return null;

}while(en.hasMoreElements()) {

Object obj=en.nextElement();if (obj instanceofSearchResult) {

SearchResult si=(SearchResult) obj;

attrs=si.getAttributes();//attrs是用户的一些相关属性,一些很重要的属性

System.out.println(attrs);

}

}

}catch(NamingException e) {

System.out.println("查找用户异常。。。");

e.printStackTrace();

}returnattrs;

}/*** 获取用户的dn

*

*@paramcn

*@return

*/

publicString getUserDN(String cn) {

Attributes attrs=getUser(cn);//distinguishedname这个属性即是用户的dn,可以打印看看

String userDN = attrs.get("distinguishedname").toString().split(":")[1].trim();returnuserDN;

}//解锁账号和下次登录需要修改密码

public voidenableUser(String userName) {

String userDN=getUserDN(userName);

BasicAttributes attrsbu= newBasicAttributes();//这个是重点,下面有话有说

attrsbu.put("userAccountControl", "512");

attrsbu.put("pwdLastSet", "0");try{

ctx.modifyAttributes(userDN, DirContext.REPLACE_ATTRIBUTE, attrsbu);

System.out.println("解锁账号成功");

}catch(NamingException e) {

System.out.println("解锁账号失败");

e.printStackTrace();

}

}//重置密码

public void updateUserPassword(String cn, String newPassword) throwsUnsupportedEncodingException, NamingException {

ModificationItem[] mods= new ModificationItem[1];

String newQuotedPassword= "\"" + newPassword + "\"";byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

mods[0] = newModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd", newUnicodePassword));//修改密码

String userDN =getUserDN(cn);

ctx.modifyAttributes(userDN, mods);

}/*** AD账户时间戳转换

*@paramaccountExpiresL

*@return

*/

public static Date adExpiresToDate(longaccountExpiresL){

Calendar calendar=Calendar.getInstance();

calendar.clear();

calendar.set(1601, 0, 1, 0, 0);

accountExpiresL= accountExpiresL/ 10000 +calendar.getTime().getTime();return newDate(accountExpiresL);

}/*** 获取AD账户失效日期

*@paramaccount

*@return

*/

publicDate getAccountExpiresToDate(String account){

Attributes attrs=getUser(account);//distinguishedname这个属性即是用户的dn,可以打印看看

String accountexpires = attrs.get("accountexpires").toString().split(":")[1].trim();//return accountexpires;

System.out.println(accountexpires);

Long expiresLong=Long.parseLong(accountexpires);

Date expiresDate=adExpiresToDate(expiresLong);

System.out.println(expiresDate);returnexpiresDate;

}/*** 上次密码修改时间

*@paramaccount

*@return

*/

publicDate getPwdLastSetTime(String account){

Attributes attrs=getUser(account);//distinguishedname这个属性即是用户的dn,可以打印看看

String pwdlastset = attrs.get("pwdlastset").toString().split(":")[1].trim();//return accountexpires;

System.out.println(pwdlastset);

Long pwdlastsetLong=Long.parseLong(pwdlastset);

Date pwdLastSetDate=adExpiresToDate(pwdlastsetLong);

System.out.println(pwdLastSetDate);returnpwdLastSetDate;

}public static void main(String[] args)throwsException{

LdapSSLUtil ldapUtil= newLdapSSLUtil();

ldapUtil.ldap_connect(adminName, adminPassword);

String account= "xxx";//重置密码

ldapUtil.updateUserPassword(account,"xxxx");

ldapUtil.getUserDN(account);

ldapUtil.getAccountExpiresToDate(account);

ldapUtil.getPwdLastSetTime(account);

ldapUtil.close_connect();

}

}

参考:

https://blog.csdn.net/xuxiaoqun0_0/article/details/82052218

https://blogs.msdn.microsoft.com/alextch/2012/05/15/how-to-set-active-directory-password-from-java-application/

https://www.iteye.com/blog/chnic-2065877

https://my.oschina.net/haison/blog/678354?p={{page}}

https://blog.csdn.net/laxsong/article/details/51344002

https://www.cnblogs.com/sunjiguang/p/9257585.html

https://www.bbsmax.com/A/q4zVZ0nGzK/

https://www.cnblogs.com/nidongde/p/5364622.html

https://blog.csdn.net/hc1017/article/details/81293323?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

https://blog.csdn.net/qq_41207282/article/details/97133887#comments

https://blog.csdn.net/hct368/article/details/97247258

https://www.cnblogs.com/amoyzhu/p/9259264.html

https://blog.51cto.com/gaowenlong/1969586

https://blog.51cto.com/gaowenlong/1969585

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Java修改AD密码,你可以使用Java的LDAP(轻型目录访问协议)库来实现。以下是一个示例代码: ```java import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.Attributes; import javax.naming.directory.BasicAttribute; import javax.naming.directory.BasicAttributes; import javax.naming.directory.ModificationItem; import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.LdapContext; import java.util.Hashtable; public class ADPasswordChanger { public static void main(String[] args) { String username = "your_username"; String oldPassword = "your_old_password"; String newPassword = "your_new_password"; String ldapURL = "ldap://your_domain_controller:389"; // 替换为你的控制器的URL Hashtable<String, Object> env = new Hashtable<>(); env.put(Context.SECURITY_AUTHENTICATION, "simple"); env.put(Context.SECURITY_PRINCIPAL, username + "@your_domain"); // 替换为你的名 env.put(Context.SECURITY_CREDENTIALS, oldPassword); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.PROVIDER_URL, ldapURL); try { LdapContext ctx = new InitialLdapContext(env, null); modifyPassword(ctx, username, newPassword); System.out.println("密码修改成功"); ctx.close(); } catch (NamingException e) { System.out.println("密码修改失败:" + e.getMessage()); } } private static void modifyPassword(LdapContext ctx, String username, String newPassword) throws NamingException { ModificationItem[] mods = new ModificationItem[1]; mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", newPassword)); ctx.modifyAttributes("CN=" + username, mods); } } ``` 在上面的代码中,你需要替换以下参数: - `your_username`:你的AD用户名 - `your_old_password`:你的AD密码 - `your_new_password`:你想要设置的新密码 - `ldap://your_domain_controller:389`:你的控制器的URL - `your_domain`:你的名 运行代码后,它将尝试使用提供的旧密码连接到AD控制器,然后修改密码为新密码。如果密码修改成功,将会输出"密码修改成功",否则会输出相应的错误信息。请确保你有相应的权限来修改AD密码。 请注意,修改AD密码可能涉及到安全性和权限方面的考虑。在实际使用中,请务必遵守相应的安全策略和最佳实践。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值