从java程序更改Active Directory用户密码

时间:2013-03-11 09:57:22

标签: java active-directory passwords ldap

我有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.

EDIT2:

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

5 个答案:

答案 0 :(得分:4)

  

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

您只有一个简单的不安全ldap://连接而不是ldaps://,因此根据上述限制无效。

详情请见: http://support.microsoft.com/kb/269190

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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

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

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

答案 3 :(得分: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));

答案 4 :(得分:0)

如果您使用的是Windows,则可以调用List<T>内部的NetUserChangePassword()函数。

使用JNA,代码将如下所示:

ArrayList

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