4

我有 Active Directory,其中有用户,我正在尝试从 Java 程序更改用户密码,如下所示:

Properties prop = new Properties();
prop.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
prop.put(Context.SECURITY_AUTHENTICATION, "simple");
prop.put(Context.SECURITY_PRINCIPAL,"user1");
prop.put(Context.SECURITY_CREDENTIALS,"pass1");
prop.put(Context.SECURITY_PROTOCOL,"ADSecurityProtocol");
prop.put(Context.PROVIDER_URL, "ldap://host:389/OU=My Org,DC=domain,DC=com");
try
{
     LdapContext ctx =new InitialLdapContext(prop,null);
     String oldPassword="pass1";
     String newPassword="passnew1";
     ModificationItem[] mods = new ModificationItem[2];
     String oldQuotedPassword = "\"" + oldPassword + "\"";
     byte[] oldUnicodePassword = oldQuotedPassword.getBytes("UTF-16LE");
     String newQuotedPassword = "\"" + newPassword + "\"";
     byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");

     mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
                   new BasicAttribute("unicodePwd", oldUnicodePassword));
     mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
                   new BasicAttribute("unicodePwd", newUnicodePassword));

     String theUserName="CN="+"user1"+",OU=My Org,DC=domain,DC=com";
     // Perform the update
     ctx.modifyAttributes(theUserName, mods);
     System.out.println("Changed Password for successfully");
     ctx.close();
}
     catch (Exception e) {
          System.err.println("Problem changing password: " + e);
}

我得到的错误信息是:

Problem changing password: javax.naming.NamingException: 
[LDAP: error code 1 - 000020D6: SvcErr: DSID-031007DB, 
problem 5012 (DIR_ERROR), data 0]; remaining name 
'CN=user1,OU=My Org,DC=domain,DC=com'

编辑1:

根据建议,我也尝试过使用端口 636 和 ldaps:

prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My Org,DC=domain,DC=com");  
Also tried
prop.put(Context.PROVIDER_URL, "ldaps://host:636/OU=My Org,DC=domain,DC=com");  

I am getting MalformedURLException: Invalid URI: 
Invalid URI: Org,DC=domain,DC=com] 

当我尝试时(不确定是否有任何东西在 636 上监听,看来是这样):

$ telnet LDAPHost 636
Escape character is '^]'.
Connection closed by foreign host.

编辑2:

Changed:
 prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My Org,DC=domain,DC=com");  
to:
 prop.put(Context.PROVIDER_URL, "ldap://host:636/OU=My%20Org,DC=domain,DC=com"); 

错误是:

javax.naming.CommunicationException: simple bind failed: host:636 
[Root exception is java.net.SocketException: Connection reset]

可能 LDAP 服务器甚至没有监听 ssl 端口:636

4

5 回答 5

5

[ unicodePwd] 属性可以在受限条件下写入 [...] 为了修改此属性,客户端必须具有与服务器的 128 位安全套接字层 (SSL) 连接。

您只有一个普通的不安全ldap://连接而不是ldaps://,因此根据上述限制将无法正常工作。

在以下位置查看更多详细信息:http: //support.microsoft.com/kb/269190

于 2013-03-11T10:08:51.753 回答
2

执行密码更改调用的 JVM 需要受到目录服务提供者的信任。这意味着将从 AD 生成的证书导入 JVM 信任库。

于 2013-04-04T14:48:13.037 回答
1

如果您在 Windows 上,那么您可以调用NetUserChangePassword()内部可用的函数netapi32.dll

使用JNA,代码将是这样的:

public static int changeActiveDirectoryUserPassword(String activeDirectoryIP, String username, String oldPassword, String newPassword)
{
    int status = Netapi32.INSTANCE.NetUserChangePassword(activeDirectoryIP, username, oldPassword, newPassword);

    switch(status)
    {
        case WinError.ERROR_INVALID_PARAMETER: // The parameter is incorrect
        case WinError.ERROR_ACCESS_DENIED: // The user does not have access to the requested information
        case WinError.ERROR_INVALID_PASSWORD: // The user has entered an invalid password
        case LMErr.NERR_InvalidComputer: // The computer name is invalid
        case LMErr.NERR_NotPrimary: // The operation is allowed only on the primary domain controller of the domain
        case LMErr.NERR_UserNotFound: // The user name could not be found
        case LMErr.NERR_PasswordTooShort: // The password is shorter than required. (The password could also be too
                                          // long, be too recent in its change history, not have enough unique
                                          // characters, or not meet another password policy requirement.)
        case LMErr.NERR_Success: // function succeeds
        default: return status;
    }
}

注意:与 ldap 方法不同,即使旧密码已过期,此方法也可以使用。

于 2018-07-25T05:40:05.387 回答
0

基本上,您需要修改unicodePwd用户的属性。

我使用 AWS Simple AD 实施,因为它基于 Samba 4,所以这个属性不起作用。你需要clearTextPassword在这种情况下使用。请参阅我的博客文章: http ://blog.techutils.space/2016/02/changeing-samba4-aws-simple-ad-user.html

注意:AWS Simple AD 尚不支持 SSL,因此请找到降低此风险的方法。

于 2016-02-29T02:24:20.750 回答
0

您必须更改属性。尝试unicodePwd改变userpassword

从 :

 mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
               new BasicAttribute("unicodePwd", oldUnicodePassword));
 mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
               new BasicAttribute("unicodePwd", newUnicodePassword));

至 :

mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
                   new BasicAttribute("userpassword", oldUnicodePassword));
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
                   new BasicAttribute("userpassword", newUnicodePassword));
于 2017-01-29T07:57:51.940 回答