如何通过编程方式更改Active Directory密码

41

我有一组测试账户将要被创建,但是这些账户会被设置为需要在第一次登录时更改密码。我想用C#编写一个程序来遍历这些测试账户并修改密码。

7个回答

74

如果你有足够的权限并且找到了正确的UserPrincipal对象,你可以使用SetPassword方法来设置密码,该方法属于UserPrincipal类。 使用FindByIdentity来查找要操作的主体对象。

using (var context = new PrincipalContext( ContextType.Domain ))
{
  using (var user = UserPrincipal.FindByIdentity( context, IdentityType.SamAccountName, userName ))
  {
      user.SetPassword( "newpassword" );
      // or
      user.ChangePassword( "oldPassword", "newpassword" );

      user.Save();
  }
}

4
顺便提一下,那只有在.NET 3.5及以上版本才可用(包括PrincipalContext等)。 - marc_s
6
请在此之后记得执行user.Save() - R.D. Alkire
很棒的解决方案。我如何使用您上面的解决方案切换“用户必须在下次登录时更改密码”? - Si8

22

这里有一个很棒的Active Directory编程快速参考:

如何使用C#操作Active Directory(几乎)所有功能

在末尾附近可以找到重置密码的代码。

public void ResetPassword(string userDn, string password)
{
    DirectoryEntry uEntry = new DirectoryEntry(userDn);
    uEntry.Invoke("SetPassword", new object[] { password });
    uEntry.Properties["LockOutTime"].Value = 0; //unlock account

    uEntry.Close();
}

问题是关于更改密码,而不是设置密码。两件不同的事情。用户知道当前密码吗? - joym8
1
太棒了!我可以在不知道旧密码的情况下更改密码。感谢 Dana Holt! - Coskun Ozogul
当您在AD中设置密码时,您还可以选择在使用临时密码时强制用户更改密码。如何使用上述代码实现此功能?谢谢。 - Si8

13

试试这段代码。对我来说有效。

public void ChangeMyPassword(string domainName, string userName, string currentPassword, string newPassword)
{
    try
    {
        string ldapPath = "LDAP://192.168.1.xx";
        DirectoryEntry directionEntry = new DirectoryEntry(ldapPath, domainName + "\\" + userName, currentPassword);
        if (directionEntry != null)

        {
            DirectorySearcher search = new DirectorySearcher(directionEntry);
            search.Filter = "(SAMAccountName=" + userName + ")";
            SearchResult result = search.FindOne();
            if (result != null)
            {
                DirectoryEntry userEntry = result.GetDirectoryEntry();
                if (userEntry != null)
                {
                    userEntry.Invoke("ChangePassword", new object[] { currentPassword, newPassword });
                    userEntry.CommitChanges();
                }
            }
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

这是从 Web 应用程序更改密码的最佳方法。它不会在服务器上创建用户文件夹,而是更改密码而不是管理员重置。这样做的好处列在此处:https://dev59.com/w3TYa4cB1Zd3GeqPrCKQ - BinaryPatrick
为什么要捕获异常再抛出它?如果必须这样做,为什么不只是使用“throw;”来保留原始的堆栈跟踪信息呢? - Jamie

2
这里是解决方案:
string newPassword = Membership.GeneratePassword(12, 4);    
string quotePwd = String.Format(@"""{0}""", newPassword);    
byte[] pwdBin = System.Text.Encoding.Unicode.GetBytes(quotePwd);    
UserEntry.Properties["unicodePwd"].Value = pwdBin;    
UserEntry.CommitChanges();

在我的情况下,我收到了消息:“服务器不愿意处理请求”。 - Samuel
需要 using System.Web.Security;,但除此之外对我来说是可行的。 - gojimmypi

0
public void ResetPassword(string userName, string Password, string newPassword)
{
    try
    {
        DirectoryEntry directoryEntry = new DirectoryEntry(Path, userName, Password);

        if (directoryEntry != null)
        {
            DirectorySearcher searchEntry = new DirectorySearcher(directoryEntry);
            searchEntry.Filter = "(samaccountname=" + userName + ")";
            SearchResult result = searchEntry.FindOne();
            if (result != null)
            {
                DirectoryEntry userEntry = result.GetDirectoryEntry();
                if (userEntry != null)
                {
                    userEntry.Invoke("SetPassword", new object[] { newPassword });
                    userEntry.Properties["lockouttime"].Value = 0;
                }
            }
        }
    }
    catch (Exception ex)
    {
        Log.Error("Password Can't Change:" + ex.InnerException.Message);
    }
}

0

可以使用.NET Framework 2.0为域帐户设置新密码。 请参见下面的工作代码:

string domainfqdn="mydomain.test.gov" //fqdn of the domain
string ldapPath =GetObjectDistinguishedName (objectClass.user,returnType.distinguishedName, args[0].ToString(),domainfqdn);
ldapPath="LDAP://" + domainfqdn + :389/"+ldapPath;

DirectoryEntry uEntry = new DirectoryEntry(ldapPath,null,null,AuthenticationTypes.Secure);
uEntry.CommitChanges();
Console.WriteLine(ldapPath);
string password="myS3cr3tPass"              
uEntry.Invoke("SetPassword", new object[] { password });
uEntry.Properties["LockOutTime"].Value = 0; //unlock account                
uEntry.CommitChanges();
uEntry.Close();             

在 uEntry 处检查参数非常重要,除非指定了 null 值,否则代码将在当前线程安全上下文下运行。


0

我在一个Windows应用程序中遇到了一个问题,如果在同一天早些时候使用“设置密码”为用户提供新密码,则在使用“更改密码”时会出现问题。这是因为我们的域有一个最小密码年龄策略。解决方案是在使用“设置密码”时也将密码更改日期设置为0(空),以便用户可以在同一天更改他们的密码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接