如何使用C#.NET跨域设置/更改Active Directory用户密码?

时间:2014-03-07 21:38:37

标签: c# .net active-directory ldap

我一直在寻找一段时间如何设置/更改密码并撤销/恢复用户但尚未找到真正适合我的解决方案。

我开始倾向于这样一个事实:即使我可以通过编程方式创建/删除/更新甚至连接/断开用户与组之间的问题。

基本上,我尝试过以下方法:

DirectoryEntry account = new DirectoryEntry("LDAP://" + adHostname + "/" + dn, adUserName, adPassword);

account.Invoke("SetPassword", "Password1");
account.Properties["LockOutTime"].Value = 0;
account.CommitChanges();

account.Invoke("SetPassword", new object[] { "Password1" });

它们最终都会抛出错误“一个或多个输入参数无效\ r \ n”

然后我尝试使用主要上下文的.NET 3.5方法。

using (var context = new PrincipalContext(ContextType.Domain, adHostname, myContainer, ContextOptions.SimpleBind, adUserName, adPassword))
    {
        using (var user = UserPrincipal.FindByIdentity(context, account.Properties["sAMAccountName"].Value.ToString()))
        {
             user.SetPassword(password);
        }
    }    

这种方法也抛出了与上面相同的错误。如果我切换一些东西(我似乎无法记住我尝试的所有组合),它有时会抛出“发生本地错误”COM异常。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:0)

看到这篇文章: https://www.codeproject.com/Articles/18102/Howto-Almost-Everything-In-Active-Directory-via-C#7

您将在所有示例中注意到我们直接绑定到directoryEntry并且未指定服务器或凭据。如果您不想使用模拟类,则可以将凭据直接发送到DirectoryEntry构造函数中。当您想要使用静态方法并且不想经历创建DirectoryContext对象以保存这些详细信息的麻烦时,模拟类很有用。同样,您可能希望定位特定的域控制器。

目标特定域控制器或凭证

您看到的代码中的所有位置:LDAP://您可以使用LDAP替换:// MyDomainControllerNameOrIpAddress以及您看到正在构建的DirectoryEntry类的任何位置,您也可以发送特定凭据。如果您需要处理您的计算机不是其林或域的成员的Active Directory,或者您希望将DC作为目标进行更改,则此功能尤其有用。

//重命名对象并直接指定域控制器和凭据

public static void Rename(string server,
    string userName, string password, string objectDn, string newName)
{
    DirectoryEntry child = new DirectoryEntry("LDAP://" + server + "/" + 
        objectDn, userName, password);
    child.Rename("CN=" + newName);
}

答案 1 :(得分:0)

"新的DirectoryEntry"不绑定用户帐户。需要搜索用户以设置密码。像这样:

DirectoryEntry account = new DirectoryEntry("LDAP://" + adHostname + "/" + dn, null, null, AuthenticationTypes.Secure | AuthenticationTypes.Sealing | AuthenticationTypes.Signing);

DirectorySearcher search = new DirectorySearcher(account);
search.Filter = "(&(objectClass=user)(sAMAccountName=" + adUserName + "))";
account = search.FindOne().GetDirectoryEntry();

account.Invoke("SetPassword", "Password1");
account.Properties["LockOutTime"].Value = 0;
account.CommitChanges();

答案 2 :(得分:0)

这个一直对我有用。希望能帮助到你。 首先添加对System.DirectoryServices.AccountManagement

的引用
    string hostName = "myDomain";
    string adminName = "admin";
    string adminPassword = "password";

    public static void ResetPassword(string username, string password)
            {
        using (PrincipalContext pContext = new PrincipalContext(ContextType.Domain, hostName, adminName, adminPassword))
                                {
                                    UserPrincipal up = UserPrincipal.FindByIdentity(pContext, username);
                                    if (up != null)
                                    {
                                        up.SetPassword(password);
                                        up.Save();
                                    }
                                }
                        }

您还可以对UserPrincipal执行各种操作,例如锁定帐户,过期密码,获取上次登录等。

答案 3 :(得分:-1)

下午好! 我已经读过几次您的问题,但我绝对不理解您问题的实质...

如果您需要更改密码,请先阅读以下材料: https://docs.microsoft.com/en-us/windows/win32/api/iads/nf-iads-iadsuser-setpassword https://docs.microsoft.com/ru-ru/office/client-developer/outlook/mapi/hresult 请记住,更改密码时,您的帐户(将代表您尝试更改密码)必须在Active Directory域中具有足够的管理权限才能更改密码!特别重要的是要注意,新密码必须符合您的域策略设置的要求!

        string distinguishedName = $"LDAP://CN=SuperUser,DC=company,DC=local";
        if (!DirectoryEntry.Exists(distinguishedName))
            return;
        DirectoryEntry deEntry = new DirectoryEntry(distinguishedName);
        try
        {
            deEntry.Invoke("SetPassword", "MyNew@#123Pass12091");
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        Console.Read();

编辑-在评论后添加

太懒惰以至于无法帮助那些不满意的用户,此外,还单击了弊端……为您特别在测试台上放置一个AD域和一个未连接到该域的客户端以进行干净检查!

static void Main(string[] args)
    {
        Console.WriteLine($"Client - {Environment.UserDomainName}\\{Environment.MachineName}");
        try
        {
            DirectoryEntry dirEntrForeignDomain = new DirectoryEntry();
            dirEntrForeignDomain.AuthenticationType = AuthenticationTypes.ServerBind;
            dirEntrForeignDomain.Path = $"LDAP://172.28.145.73/DC=kul,DC=local";
            dirEntrForeignDomain.Username = $"Администратор@kul.local";
            dirEntrForeignDomain.Password = $"Qwerty123";

            SetPasswordUser(dirEntrForeignDomain); // but it is better to use OFFICIAL - AuthenticablePrincipal.SetPassword(String)
            ResetPasswordUser(dirEntrForeignDomain);
            UnResetPasswordUser(dirEntrForeignDomain);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
        Console.Read();
    }

    static public void SetPasswordUser(DirectoryEntry de)
    {
        using (DirectorySearcher dirSearchUser = new DirectorySearcher(de))
        {
            dirSearchUser.Filter = "(&(objectClass=user)(sAMAccountName=test))";
            SearchResult searchResUser = dirSearchUser.FindOne();
            if (searchResUser != null)
            {
                DirectoryEntry dirEntryFoundUser = searchResUser.GetDirectoryEntry();
                dirEntryFoundUser.Invoke("SetPassword", new object[] { "Qwerty!!!" });
                dirEntryFoundUser.CommitChanges();
                Console.WriteLine("Set password is - Qwerty!!!");
            }
        }
    }
    static public void ResetPasswordUser(DirectoryEntry de)
    {
        using (DirectorySearcher dirSearchUser = new DirectorySearcher(de))
        {
            dirSearchUser.Filter = "(&(objectClass=user)(sAMAccountName=test))";
            SearchResult searchResUser = dirSearchUser.FindOne();
            if (searchResUser != null)
            {
                DirectoryEntry dirEntryFoundUser = searchResUser.GetDirectoryEntry();
                dirEntryFoundUser.Properties["pwdLastSet"].Value = 0;
                dirEntryFoundUser.CommitChanges();
                Console.WriteLine("ResetPasswordUser!");
            }
        }
    }
    static public void UnResetPasswordUser(DirectoryEntry de)
    {
        using (DirectorySearcher dirSearchUser = new DirectorySearcher(de))
        {
            dirSearchUser.Filter = "(&(objectClass=user)(sAMAccountName=test))";
            SearchResult searchResUser = dirSearchUser.FindOne();
            if (searchResUser != null)
            {
                DirectoryEntry dirEntryFoundUser = searchResUser.GetDirectoryEntry();
                dirEntryFoundUser.Properties["pwdLastSet"].Value = -1;
                dirEntryFoundUser.CommitChanges();
                Console.WriteLine("UnResetPasswordUser ...");
            }
        }
    }
  • 为另一个域的用户设置密码
  • 为其他域中的用户设置更改密码的要求
  • 对于其他域中的用户,取消设置更改密码的要求

日志

客户端-DESKTOP-KUL \ DESKTOP-KUL
设置密码为-Qwerty !!!
ResetPasswordUser!
UnResetPasswordUser ...

很奇怪,您通过“ UserPrincipal”失败了“ SetPassword” ...