使用 Apache LDAP API 在下次登录 Active Directory 时强制更改密码

Force password change on next login with Active Directory using Apache LDAP API

我们使用 Active Directory (AD),当添加用户时,他们会设置密码和强制执行“用户必须在下次登录时更改密码”的标志,这会导致 AD 属性 pwdLastSet=0

我有一个 Java 应用程序使用 Apache LDAP API 进行身份验证,但是当我这样做时,我收到错误代码 49 INVALID_CREDENTIALS 并且没有更改密码的指示。

我如何使用 Apache LDAP API 检测到用户必须先更改密码?

我的简单验证器:

    public void authenticate(String uid, String password) {
    String status = "";
    try {
        LdapConnectionConfig config = new LdapConnectionConfig();
        config.setUseSsl(true);
        config.setLdapHost("activedirectory.domain.net");
        config.setLdapPort(636);
        config.setTrustManagers(new NoVerificationTrustManager());
        config.setName(_ldapMgmtUser);
        config.setCredentials(_ldapMgmtPassword);

        final DefaultPoolableLdapConnectionFactory factory = new DefaultPoolableLdapConnectionFactory(config);
        final LdapConnectionPool pool = new LdapConnectionPool(factory);
        pool.setTestOnBorrow(true);
        final LdapConnectionTemplate ldapConnectionTemplate = new LdapConnectionTemplate(pool);

        final PasswordWarning warning = ldapConnectionTemplate.authenticate(_rootDn, "(sAMAccountName=" + uid + ")",
                SearchScope.SUBTREE, password.toCharArray());

        status = "User credentials authenticated";
        if (warning != null) {
            status = status + " \n Warning!!" + warning.toString();
        }
        System.out.println(status);
    } catch (final PasswordException e) {
        System.err.println("############# PasswordException #############");
        status = e.toString();
        e.printStackTrace();
    } catch (Exception e) {
        System.err.println("############# Exception #############");
        e.printStackTrace();

    } finally {
    }
    return;
}

我注意到当使用 LdapConnectionTemplateauthenticate(...)(如上)时,它不会 return 异常中的任何有用的错误代码并且没有 PasswordWarning。 这种情况 return 不应该是 PasswordWarning 吗? https://nightlies.apache.org/directory/api/2.0.1/apidocs/org/apache/directory/ldap/client/template/PasswordWarning.html

如果我使用: LdapNetworkConnectionconnection.bind(...) 它 return 是一个 LdapException 和消息 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 773, v3839 其中 773 是预期的。

感觉LdapConnectionTemplate有(几个)bug

完整代码:

    public void authenticateWithBind(String uid, String password) {
        String status = "";
        LdapConnection connection = null;
        try {
            LdapConnectionConfig config = new LdapConnectionConfig();
            config.setUseSsl(true);
            config.setLdapHost("activedirectory.domain.net");
            config.setLdapPort(636);
            config.setTrustManagers(new NoVerificationTrustManager());
            config.setName(_ldapMgmtUser);
            config.setCredentials(_ldapMgmtPassword);

            connection = new LdapNetworkConnection(config);
            connection.bind(_ldapMgmtUser, _ldapMgmtPassword);

            EntryCursor cursor = connection.search(_rootDn, "(sAMAccountName=" + uid + ")", SearchScope.SUBTREE, "*");
            
            while (cursor.next()) {
                Entry entry = cursor.get();
                System.out.println("DN: " + entry.getDn());
                System.out.println("Attribute: " + entry.get("pwdLastSet"));

                connection.bind(entry.getDn(), password);
                status = "User credentials authenticated";
                System.out.println(status);
            }
        } catch (LdapException e) {
            System.err.println("############# LdapException #############");
            e.printStackTrace();
            System.err.println("Error message: " + e.getMessage());

        } catch (Exception e) {
            System.err.println("############# Exception #############");
            e.printStackTrace();
            System.err.println("Error message: " + e.getMessage());
        } finally {
            closeConnection(connection);
        }
        return;
    }