java 当用户设置了“用户必须在下次登录时更改密码”标志时,使用LDAP更新用户密码,导致错误49,子代码773

3lxsmp7m  于 2023-02-18  发布在  Java
关注(0)|答案(2)|浏览(262)

当我尝试通过LDAP更改某个用户的密码时,在该用户的AD帐户中设置了下次登录时必须更改密码,我收到以下错误:
cause: javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090447, comment: AcceptSecurityContext error, data 773, v3839
子代码773表示用户必须重置密码,这正是我现在要做的。
使用以下代码,如果上述标志为notset,则可以成功更改密码:

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 {
          //
        }
    }

那么,你是否知道有甚么地方需要改变,又或者是甚么原因令它不能运作呢?

66bbxpm5

66bbxpm51#

我的猜测是,您只需要删除这些行:

// Change the BindUser
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userCtx.getNameInNamespace());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, oldPassword);

你不能使用旧密码进行身份验证,因为它不再有效。但是你也不需要在更改密码时绑定用户自己的凭据,因为你必须在请求中提供旧密码。
以下几行也可能给您带来麻烦:

Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));

密码必须转换成unicode字节,但是它们也必须用双引号括起来("),所以在传递给toUnicodeBytes()之前,你可能需要加上双引号。

ia2d9nvy

ia2d9nvy2#

您可以通过两个步骤进行管理:
如果设置了“用户必须更改密码”,则应将用户的密码更改为初始密码admin(bind)。

Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(oldPassword));
                Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(initialPassword));

然后,在用(初始)密码与用户绑定之后,用户(他自己)应当改变他的密码。

Attribute oldattr = new BasicAttribute("unicodePwd", toUnicodeBytes(initialPassword)));
                Attribute newattr = new BasicAttribute("unicodePwd", toUnicodeBytes(newPassword));

(with双引号,如果你喜欢)
这也可以在用户密码过期的情况下工作。

相关问题