java - 无法使用 Spring LDAP 更新 AD 中的密码和用户帐户控制

标签 java spring active-directory spring-ldap

我是 Spring LDAP 和 Active Directory 的新手,在更新 AD 中新创建的用户的密码时遇到问题。

使用 SPRING LDAP 我首先在 AD 中成功创建了用户,然后在出现以下异常时尝试更新用户的密码和用户帐户控制。 我们已经尝试了 1 周但未能解决。非常感谢任何帮助/指导。

我浏览了很多博客并尝试了下面两个博客中提到的方法,但仍然被阻止并遇到相同的异常:

How do I resolve "WILL_NOT_PERFORM" MS AD reply when trying to change password in scala w/ the unboundid LDAP SDK?

Adding a user with a password in Active Directory LDAP

堆栈跟踪:

16:43:56,991 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)  INFO [http-localhost-127.0.0.1-8080-1] (HelperDao.java:26) - HelperDao.getNextUserId(): entry

16:43:57,007 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) Hibernate:   SELECT LTRIM(TO_CHAR( IP_USER_XDUSERID_SEQ.nextval, '000000000000000000000000000')) ID from dual

16:43:57,164 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)  INFO [http-localhost-127.0.0.1-8080-1] (HelperDao.java:30) - HelperDao.getNextUserId(): exit

16:47:17,051 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) 16:47:17.051 [http-localhost-127.0.0.1-8080-1] ERROR com.st.liotroevo.web.dao.UserADRepository - catching

16:47:17,051 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) javax.naming.OperationNotSupportedException: [LDAP: error code 53 - 0000200D: SvcErr: DSID-031A0FC0, problem 5003 (WILL_NOT_PERFORM), data 0
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1) 
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.ldap.LdapCtx.mapErrorCode(LdapCtx.java:3160) ~[?:1.7.0_45]
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:3033) ~[?:1.7.0_45]
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.ldap.LdapCtx.processReturnCode(LdapCtx.java:2840) ~[?:1.7.0_45]
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.ldap.LdapCtx.c_modifyAttributes(LdapCtx.java:1478) ~[?:1.7.0_45]
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.toolkit.ctx.ComponentDirContext.p_modifyAttributes(ComponentDirContext.java:273) ~[?:?]
16:47:17,067 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.modifyAttributes(PartialCompositeDirContext.java:190) ~[?:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.jndi.toolkit.ctx.PartialCompositeDirContext.modifyAttributes(PartialCompositeDirContext.java:179) ~[?:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at javax.naming.directory.InitialDirContext.modifyAttributes(InitialDirContext.java:167) ~[?:1.7.0_45]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_45]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_45]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_45]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_45]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.springframework.transaction.compensating.support.CompensatingTransactionUtils.performOperation(CompensatingTransactionUtils.java:69) ~[spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.springframework.ldap.transaction.compensating.manager.TransactionAwareDirContextInvocationHandler.invoke(TransactionAwareDirContextInvocationHandler.java:85) ~[spring-ldap-core-2.0.2.RELEASE.jar:2.0.2.RELEASE]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.sun.proxy.$Proxy69.modifyAttributes(Unknown Source) ~[?:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.st.liotroevo.web.dao.UserADRepository.update(UserADRepository.java:104) [classes:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.st.liotroevo.web.service.UserService.updateUser(UserService.java:92) [classes:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at com.st.liotroevo.web.service.serviceImpl.IPRegistrationServiceImpl.createUser(IPRegistrationServiceImpl.java:72) [classes:?]
16:47:17,099 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.7.0_45]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[?:1.7.0_45]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.7.0_45]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at java.lang.reflect.Method.invoke(Method.java:606) ~[?:1.7.0_45]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.jboss.ws.common.invocation.AbstractInvocationHandlerJSE.invoke(AbstractInvocationHandlerJSE.java:111) [jbossws-common-2.0.2.GA.jar!/:2.0.2.GA]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.jboss.wsf.stack.cxf.JBossWSInvoker._invokeInternal(JBossWSInvoker.java:181) [jbossws-cxf-server-4.0.2.GA.jar!/:4.0.2.GA]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.jboss.wsf.stack.cxf.JBossWSInvoker.invoke(JBossWSInvoker.java:127) [jbossws-cxf-server-4.0.2.GA.jar!/:4.0.2.GA]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58) [cxf-rt-core-2.4.6.jar!/:2.4.6]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [?:1.7.0_45]
16:47:17,115 INFO  [stdout] (http-localhost-127.0.0.1-8080-1)       at java.util.concurrent.FutureTask.run(FutureTask.java:262) [?:1.7.0_45]

下面是代码片段:

ldap.url=ldaps://url:636
ldap.userDn=CN=IP User,OU=AdminAccounts,DC=stp-qa,DC=st,DC=com
ldap.password=dummyPass
ldap.base=OU=ST,OU=People,DC=stp-qa,DC=st,DC=com
ldap.clean=false

@Entry(objectClasses = {  "top", "person", "organizationalPerson","user","st-individualpassportuser"})
public final class User {

    @Id
    private Name dn;

    @Attribute(name = "mail")
    private String email;

    @Attribute(name = "cn")
    @DnAttribute(value="cn",index=0)
    private String fullName;

    @Attribute(name = "givenName")
    private String firstName;

    @Attribute(name = "sn")
    private String lastName;

    @Attribute(name = "st-AccValidationStatus")
    private String accountStatus;

    @Attribute(name = "st-entryStatus")
    private String validationStatus;

    @Attribute(name = "whenCreated")
    private String creationDate;

    @Attribute(name = "st-ValidatedOn")
    private String validationDate;

    @Attribute(name = "st-ValidatedBy")
    private String validatedBy;

    @Attribute(name = "st-currentLogon")
    private String lastLogon;

    @Attribute(name = "st-loginRedirectURL")
    private String loginRedirectUrl;

    @Attribute(name = "st-jvCompany")
    private String jvCode;

    @Attribute(name = "sAMAccountName")
    private String samAccount;

    @Attribute(name = "st-userSpecifedCompany")
    private String employerName;

    @Attribute(name = "postalCode")
    private String zipCode;

    @Attribute(name="st-xduserid")
    private String xdUserId;

    @Attribute(name="st-Logincount")
    private String loginCount;

    @Attribute(name="unicodePwd")
    private byte[] unicodePassword;

    @Attribute(name="userAccountControl")
    private String userAccountControl;

    @Attribute(name="st-AccLastValidated")
    private String userAccLastValidated;

    @Attribute(name="st-secretQuestion")
    private String userSecretQuestion;

    @Attribute(name="st-secretAnswer")
    private String userAnswerToSecretQuestion;
    }

用于密码计算的 Java 类:

/**
 * Add unicode Password to userObject.
 * Ldap does not allow to set password/userAccountControl during creation of user by design, So need to update user after creation in AD with password and userAccountControl.
 * @param password
 */
private void addPasswordToUserProfile(String password) {

    String newQuotedPassword = "\"" +  password + "\"";
    try {
        byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
            int UF_NORMAL_ACCOUNT = 0x0200;
            int UF_PASSWORD_EXPIRED = 0x800000;
            adUserBean.setUserAccountControl(Integer.toString(UF_NORMAL_ACCOUNT + UF_PASSWORD_EXPIRED));
            adUserBean.setUnicodePassword(newUnicodePassword);
    } catch (UnsupportedEncodingException e) {
        logger.catching(e);
    }
}

存储库.Java

@Repository
public class UserADRepository {

    @Autowired
    private LdapTemplate ldapTemplate;

    public User create(User user) {
        ldapTemplate.create(user);
        return user;
    }

    public User findByFullName(String fullName) {
        return ldapTemplate.findOne(
                LdapQueryBuilder.query().where("cn").is(fullName), User.class);
    }

    /**
     * Find user in LDAP based on User SamAccountName
     * @param samAccount
     * @return
     */
    public User findBySamAccountName(String samAccount) {
        User usr = null;
        try {
            usr = ldapTemplate.findOne(
                    LdapQueryBuilder.query().where("sAMAccountName")
                            .is(samAccount), User.class);
        } catch (EmptyResultDataAccessException emptyException) {
            return usr;
        }
        return usr;
    }

/**
 * Find user in LDAP based on User DN (distinguisedName) 
 * @param dn
 * @return
 */
    public User findByDn(Name dn) {
        User usr = null;
        try {
            usr = ldapTemplate.findByDn(dn, User.class);
        } catch (NameNotFoundException e) {
            return usr;
        }
        return usr;
    }

    /**
     * Update user in AD 
     * @param User
     */
    public void update(User User) {
        ldapTemplate.update(User);
    }

    public void delete(User User) {
        ldapTemplate.delete(User);
    }

预先感谢您提供解决此问题的帮助或指导。

最佳答案

更新 AD 密码使用单独的方法,似乎 LdapTemplate.update() 没有为密码定义正确的 ModificationItem。

        public void setPassword(Person p){
        String relativeDn = getRelativeDistinguishedName(person.getDistinguishedName());
        LdapNameBuilder ldapNameBuilder = LdapNameBuilder.newInstance(relativeDn);
        Name dn  = ldapNameBuilder.build();

        DirContextOperations context = ldapTemplate.lookupContext(dn);

        Attribute attr = new BasicAttribute("unicodepwd", encodePassword(person.getPassword()));
        ModificationItem item = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);

        ldapTemplate.modifyAttributes(dn, new ModificationItem[] {item});   
        }

关于java - 无法使用 Spring LDAP 更新 AD 中的密码和用户帐户控制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28964782/

相关文章:

java - 是否可以将数组中的索引与颜色进行比较?

Java Swing Jbutton 访问另一个类中按下的按钮?

java - 如何在初始化期间声明 spring bean

sql-server - SQL Server 中 ADSI 链接的可用字段

c# - 在 Owin 中针对 Power Bi 进行身份验证

java - 算术运算使 0、1 和 2 返回 0 | 3、4 和 5 返回 1 等

java - 如何在运行时修改 Web 应用程序中的属性文件?

Spring cloud contracts插件更改源集

java - Spring 或 JSP 显示多条相同的错误消息而不是一条

php - 如何使用 ZF2 在 ldap Active Directory(AD) 中添加属性成员/memberOf