Java JNDI连接AD认证成功 修改密码报LDAP error code32求助
问题根因及修复方案
你遇到的LDAP error code 32(NO_OBJECT)和后续密码修改失败是两个独立问题,逐个修复即可:
1. 直接触发当前报错的原因:DN路径重复拼接导致找不到对象
你当前配置里Context.PROVIDER_URL已经指定了根后缀dc=trial,dc=com,调用modifyAttributes时又传入了完整DNCN=Test1,CN=Users,DC=trial,DC=com,JNDI会自动将传入的相对路径和连接根路径拼接,最终实际查询的路径变成CN=Test1,CN=Users,DC=trial,DC=com,DC=trial,DC=com,自然找不到目标对象。
修复方式二选一即可:
- 方案1:修改PROVIDER_URL为不带根后缀的地址:
ldap://localhost:389,后续操作保留全路径DN写法 - 方案2:保留现有PROVIDER_URL配置,修改操作传入的用户DN为相对路径:
CN=Test1,CN=Users
验证技巧:修改路径后可以先加一段用户查询逻辑,确认能正常搜到test1用户再做密码修改操作,避免反复踩路径的坑。
2. 路径修复后会遇到的问题:AD密码修改逻辑不符合规范
就算路径改对,你现在写的修改userPassword属性的逻辑在AD域里默认也不会生效,AD域服务的密码存储属性是unicodePwd,修改时必须满足以下要求:
- 不能用普通389端口的明文LDAP连接,必须用LDAPS加密连接(默认端口636),否则域控会拒绝密码修改请求
- 密码值必须使用
UTF-16LE编码,且密码字符串两端需要包裹英文双引号,比如你要设置密码为Panda23*,实际传入的字节是"Panda23*"转成UTF-16LE的结果 - 如果是普通用户修改自身密码,需要携带旧密码做校验;如果是管理员重置其他用户密码,需要给绑定的账号分配对应重置密码的权限
修正后的核心代码参考
import javax.naming.Context; import javax.naming.NamingException; import javax.naming.AuthenticationException; import javax.naming.directory.DirContext; import javax.naming.ldap.LdapContext; import javax.naming.ldap.InitialLdapContext; import javax.naming.directory.ModificationItem; import javax.naming.directory.BasicAttribute; import java.util.Hashtable; public class Password_ADTesting{ public static void main(String[] args){ LdapContext ctx = null; try{ Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); env.put(Context.SECURITY_AUTHENTICATION, "Simple"); env.put(Context.SECURITY_PRINCIPAL, "test1@trial.com"); env.put(Context.SECURITY_CREDENTIALS, "Panda123*"); env.put(Context.SECURITY_PROTOCOL, "ssl"); // 测试环境使用自签名证书时,可自定义信任所有证书的SocketFactory实现跳过校验,生产环境必须正规配置证书信任 // 改用LDAPS 636端口,不带根后缀避免路径拼接问题 env.put(Context.PROVIDER_URL, "ldaps://localhost:636"); ctx = new InitialLdapContext(env,null); System.out.println("Connection Successfull"); ModificationItem[] mods = new ModificationItem[1]; // AD密码修改用unicodePwd属性,按要求编码 String newPassword = "\"Panda23*\""; byte[] passwordBytes = newPassword.getBytes("UTF-16LE"); mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("unicodePwd", passwordBytes)); // 用全路径DN操作 ctx.modifyAttributes("CN=Test1,CN=Users,DC=trial,DC=com", mods); System.out.println("Password modify Success"); }catch(AuthenticationException authEx) { System.out.println("Active Directory Authentication failed"); authEx.printStackTrace(); }catch(Exception e){ System.out.println("Password Cannot be Changed"); e.printStackTrace(); }finally { if(ctx != null) { try { ctx.close(); } catch (NamingException e) { e.printStackTrace(); } } } } }
额外注意
如果域控没有部署AD证书服务,默认是不会开启636端口LDAPS服务的,需要先在域控服务器上安装配置Active Directory证书服务并绑定证书后,LDAPS连接才能正常建立。
内容的提问来源于stack exchange,提问作者tinu
相关产品推荐
相关产品推荐

