AD用户设下次登录需改密码时,LDAP改密码报错误49(子码773)求助
问题:AD用户设置「下次登录必须更改密码」时,LDAP修改密码失败
当AD用户账户被标记为「下次登录必须更改密码」时,通过LDAP执行密码修改操作会抛出以下错误:cause: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090447, comment: AcceptSecurityContext error, data 773, v3839
LDAP错误子码773的含义是「用户必须重置密码」,但当前操作正是要完成密码重置。而未设置该标志时,以下代码可以正常修改密码:
public void updateUserPassword(String user, String oldPassword, String newPassword) throws NamingException, LoginException { try { InitialDirContext ctx = this.getContext(); String filter = "(&(objectClass=user)(sAMAccountName=" + user + "))"; String baseDn = (String) this.getActiveDirectoryProps().get("baseDN_User"); // Search for user entry SearchControls ctls = new SearchControls(); ctls.setSearchScope(SearchControls.SUBTREE_SCOPE); ctls.setReturningObjFlag(true); String[] returnAttrs = new String[3]; returnAttrs[0] = "cn"; // Common Name returnAttrs[1] = "displayName"; returnAttrs[2] = "description"; NamingEnumeration<SearchResult> enumSearchResult = ctx.search(baseDn, filter, returnAttrs, ctls); if (enumSearchResult.hasMore()) { SearchResult result = enumSearchResult.next(); DirContext userCtx = (DirContext) result.getObject(); // Change the BindUser ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword); // Update password Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword)); Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword)); ModificationItem olditem = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, oldattr); ModificationItem newitem = new ModificationItem(DirContext.ADD_ATTRIBUTE, newattr); String dn = userCtx.getNameInNamespace(); ctx.modifyAttributes(dn, new ModificationItem[]{olditem, newitem}); } ctx.close(); } catch (final NamingException nE) { // } catch (Exception E) { // } finally { // } }
失败原因
核心问题在于用户账户状态与绑定权限冲突:
- 当AD用户被标记为「下次登录必须改密码」时,账户处于受限状态,无法通过自身旧密码完成LDAP绑定操作(AD的安全机制限制)。
- 当前代码中,搜索到用户后会尝试将LDAP上下文切换为该用户(用旧密码重新绑定),这一步会触发AD的校验,直接返回773错误,导致后续密码修改操作无法执行。
修改方案
需要使用拥有AD用户密码重置权限的管理员账户来执行操作,同时调整代码逻辑:
1. 移除用户自身绑定的代码
删除以下两行切换绑定用户的代码,确保初始的InitialDirContext是用管理员账户创建的(即getContext()方法返回管理员权限的上下文):
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace()); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);
2. 优化密码修改逻辑(可选)
AD支持直接用REPLACE_ATTRIBUTE修改密码,替代原有的「移除旧密码+添加新密码」逻辑,代码更简洁:
// 替换原有的密码修改代码段 Attribute newPwdAttr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword)); ModificationItem pwdModItem = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, newPwdAttr); ctx.modifyAttributes(dn, new ModificationItem[]{pwdModItem});
3. 清除「下次登录必须改密码」标志
修改密码后,添加代码将用户的pwdLastSet属性设置为-1,清除强制改密码的标记:
// 在密码修改完成后添加这段代码 Attribute pwdLastSetAttr = new BasicAttribute("pwdLastSet", "-1"); ModificationItem pwdLastSetMod = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, pwdLastSetAttr); ctx.modifyAttributes(dn, new ModificationItem[]{pwdLastSetMod});
内容的提问来源于stack exchange,提问作者windy
相关产品推荐
相关产品推荐

