【问题标题】:How do I search for a user in a particular OU on a remote LDAP server?如何在远程 LDAP 服务器上的特定 OU 中搜索用户?
【发布时间】:2014-11-14 15:15:28
【问题描述】:

我想使用 .NET 3.5 中引入的 AccountManagement 命名空间来查找用户并设置他们的密码。但是,ADLDS 服务器不是我们公司域的一部分,所以我使用的是ContextType.Machine。当我搜索用户时,它从未找到(我怀疑它在错误的容器中搜索,但根据使用 ContextType.Machine 时的文档,您无法指定容器)。

using (var context = new PrincipalContext(ContextType.Machine, "test-server", null, "username", "password")) {
    using (var u = UserPrincipal.FindByIdentity(context, "SuperAdmin")) {
        //u is always null.   :(
    }
}

但是,我知道我可以使用普通的 ol' DirectoryEntry 找到用户:

using (var de = new DirectoryEntry("LDAP://test-server:389/CN=SuperAdmin,CN=SuperUsers,OU=test-server,DC=foo,DC=bar,DC=com", "username", "password", AuthenticationTypes.Secure)) {
    //The user is found, but SetPassword fails with "The directory property cannot be found in the cache"
    de.Invoke("SetPassword", new object[] { "foobar" });
}

最后要指出的是,我可以使用 ADSI Edit 来更改具有这些相同凭据的密码。是否可以使用较新的目录对象来执行此搜索?

【问题讨论】:

    标签: c# active-directory ldap adlds


    【解决方案1】:

    这确实是一个老问题,但最近我不得不从事一个类似的项目......如果有人遇到同样的问题,我会发布答案。

    使用UserPrincipal 类找不到user 的原因是,正如您提到的,您正在使用ContextType.Machine 进行搜索。但是在 DirectEntry 类中,你只是在做一个简单的 LDAP:// 查询。

    这是我的解决方案。

    我将我的服务器信息存储在.config 文件中。

    ... 
    //Server name and port
    <add key ="ADLDS_Server" value="Servername:port"/> 
    //Note* depending on structure container will be different for everybody
    <add key ="ADLDS_Container" value="CN=Some Value, DC=some value,DC=value"/>
    ...
    

    然后我创建了返回PrincipalContext 对象的ADLDSUtility 类。

    ...
    using System.DirectoryServices.AccountManagement
    ...
    public class ADLDSUtility
    {
        public static ContextOptions ContextOptions = ContextOptions.SecureSocketLayer | ContextOptions.Negotiate;
    
        public static PrincipalContext Principal
        {
            get
            {
                return new PrincipalContext(
                   ContextType.ApplicationDirectory,
                   ConfigurationManager.AppSettings["ADLDS_Server"],
                   ConfigurationManager.AppSettings["ADLDS_Container"],
                   //you can specify username and password if need to
                   ContextOptions);
            }
        }
    

    从那里,我写了一个method,它接受 (username, currentPassword and newPassword) 作为参数。

    public void ChangePassword(string userName, string currentPassword, string newPassword)
        {
            using (PrincipalContext ctx = ADLDSUtility.Principal)
            {
                using (UserPrincipal principal = new UserPrincipal(ctx))
                {
                    using (var searchUser = UserPrincipal.FindByIdentity(ctx, IdentityType.UserPrincipalName, userName))
                    {
                        if (searchUser != null)
                        {
                            searchUser.ChangePassword(currentPassword, newPassword);
                            // searchUser.SetPassword(newPassword);
                            if (String.IsNullOrEmpty(searchUser.Guid.ToString()))
                            {
                                throw new Exception("Could not change password");
                            }
                        }
                    }
                }
            }
        }
    

    在本例中,我通过UserPrincipalName 搜索用户。但我们不限于此。我们也可以通过IdentityType.Guid等搜索用户。

    现在searchUser 有两种涉及密码的方法。我提供了它们。

    //requires current and new password
    searchUser.ChangePassword(currentPassword, newPassword);
    //setting a password. Only requires new password.
    searchUser.SetPassword(newPassword);
    

    注意最好使用 SSL 来设置或更改密码。*

    【讨论】:

      猜你喜欢
      • 2021-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多