Java JNDI操作LDAP如何通过sAMAccountName修改用户属性
问题原因与解决方案
DirContext.modifyAttributes方法的第一个参数,需要传入待修改LDAP条目的完整可分辨名称(DN),也就是条目在LDAP目录树里的全路径。
你之前传入sr.getName()报错,根本原因和CN里的空格没有任何关系——LDAP原生支持CN属性值包含空格,你手动替换空格为下划线反而会导致CN匹配错误。真正的问题是:
- 你调用
search()方法时指定了搜索基准节点searchBase = "OU=VPN,OU=Exterieurs,DC=chu,DC=lan",返回的SearchResult对象调用getName()拿到的只是条目相对于这个搜索基准的相对路径(RDN),也就是你看到的CN=Maintenance Axians,缺少上层的OU、DC路径,LDAP服务端无法仅凭这个相对路径定位到目标用户,所以返回DIR_ERROR。
正确传参方法
有两种方式可以拿到正确的用户DN,推荐第一种,不容易出错:
- 调用
SearchResult的getNameInNamespace()方法,这个方法会直接返回条目在LDAP目录中的全局完整DN,不需要手动拼接路径。 - 手动拼接相对路径和搜索基准:
sr.getName() + "," + searchBase,效果和上面的方法一致,但如果后续调整搜索基准路径容易漏改,不推荐。
代码修正点
- 首先在搜索遍历用户的逻辑里,提前把目标用户的完整DN存下来,注意你代码里前后上下文变量名不一致:前面初始化的DirContext实例叫
ldapCtx,后面修改属性时写的是ctx,要统一变量名避免空指针。
修正后的核心代码如下:
// 提前定义变量存目标用户DN String targetUserDn = null; while (answer.hasMoreElements()) { SearchResult sr = (SearchResult)answer.next(); // 直接获取全局完整DN targetUserDn = sr.getNameInNamespace(); Attributes attrs = sr.getAttributes(); displayName = attributeToString(attrs.get("displayName")); System.out.println(" --> displayName : " + displayName); sAMAccountName = attributeToString(attrs.get("sAMAccountName")); memberof = attributeToString(attrs.get("memberof")); crnrDomainassoc01position = attributeToString(attrs.get("crnrDomainassoc01position")); accountExpires = attributeToString(attrs.get("accountExpires")); java.util.Date expiracy = timeToDate(accountExpires); accountExpiresFormat = new SimpleDateFormat("'le' dd/MM/yyyy 'à' kk:mm:ss").format(expiracy) ; } // 校验逻辑、日期转换逻辑保持不变... // 执行属性修改 Attribute attribute = new BasicAttribute("accountExpires", dateToTime(dateExpirationMarge)); ModificationItem[] item = new ModificationItem[1]; item[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attribute); // 传入完整DN,使用正确初始化的ldapCtx实例 ldapCtx.modifyAttributes(targetUserDn, item);
额外注意事项
accountExpires是AD特有的属性,存储的是Windows FILETIME格式值(从1601年1月1日UTC零点开始计算的100纳秒间隔数),要确认你的dateToTime方法转换逻辑正确,如果需要设置账户永不过期,属性值要传0或者9223372036854775807。- 你当前拼接LDAP搜索过滤器时直接把用户输入的
compteVPN拼入字符串,存在LDAP注入风险,建议对输入值做特殊字符转义后再拼接。
内容的提问来源于stack exchange,提问作者Pandalex
相关产品推荐
相关产品推荐

