【问题标题】:Query LDAP server using System.DirectoryServices.AccountManagement使用 System.DirectoryServices.AccountManagement 查询 LDAP 服务器
【发布时间】:2013-06-25 19:43:23
【问题描述】:

我正在尝试在 LDAP 上运行查询,但出现 UnauthorizedAccessException @ new PrincipalSearcher(qbeUser) 异常。 (见下面的代码)

我不明白为什么应用程序在我运行时无权运行此查询 ldapsearch 命令行工具运行良好。

        using(PrincipalContext ctx = new PrincipalContext(ContextType.Machine, "machineName"))
        {
            using(UserPrincipal qbeUser = new UserPrincipal(ctx))
            {
                using (PrincipalSearcher srch = new PrincipalSearcher(qbeUser))
                {
                    foreach (var found in srch.FindAll())
                    {
                        var user = (UserPrincipal)found;
                        Console.WriteLine(user.GivenName + " " + user.Surname +  " " + user.EmailAddress);
                    }
                }
            }
        }

【问题讨论】:

  • 当你从命令行使用ldapsearch时,你是在以管理员身份运行命令行实例吗?
  • 是的,但是我的帐户是管理员组的一部分,所以我希望可以工作。无论哪种方式,我在管理员下运行 Visual Studio,也尝试像 Debug>Debug As Administrator 一样运行...仍然无法正常工作。

标签: c# .net ldap lotus-domino


【解决方案1】:

这是一个IBM technote,介绍如何在 Domino 服务器端收集 LDAP 的调试数据。我建议从一开始就使用 LDAPDEBUG=7 设置,并将服务器上的控制台日志输出与您的 ldapsearch 查询和程序查询进行比较。

您可能需要注意的是绑定操作期间的身份验证。您没有提到您是否在 ldapsearch 命令行(-D 和 -w 参数)中传递了任何身份验证信息,并且您没有提及 SSO——我什至不确定 Domino LDAP 是否参与任何 SSO .记录在服务器上的数据应该有助于澄清您的查询用于绑定的身份(如果有的话)。 Domino 目录上的正常设置可以防止匿名查询,而且我认为它还会限制没有编辑权限(或更高权限)的用户查询其他用户帐户时可用的属性。

如果您没有服务器的管理权限,或者您可以在其上复制问题的测试服务器,则必须与实际管理员协调。您不希望 LDAPDEBUG 设置的开启时间过长。

【讨论】:

  • 我没有传递任何凭据。这是我正在运行的命令 ldapsearch -L -h hostname "objectClass=*" givenname sn mail 。如何在 C# 中实现相同的命令?谢谢
  • 对不起,我对C#中的相关类不熟悉。我仍然非常强烈建议您在服务器上使用 LDAPDEBUG 设置。这是查看您的代码真正发送到服务器的最佳方式。了解您的代码发送的内容与 ldapsearch 发送的内容之间的区别是解决此问题的关键。
  • 谢谢理查德。你说的是调试它的正确方法,不幸的是我没有那么奢侈,因为我必须尽快完成。
【解决方案2】:

请看下面的代码:

        using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "DOMAINNAME"))
        {
            using(UserPrincipal qbeUser = new UserPrincipal(ctx))
            {
                using (PrincipalSearcher srch = new PrincipalSearcher(qbeUser))
                {
                    foreach (var found in srch.FindAll())
                    {
                        var user = (UserPrincipal)found;
                        Console.WriteLine(user.GivenName + " " + user.Surname +  " " + user.EmailAddress);
                    }
                }
            }
        }

如果我这样做,它可以正常工作,但我无法指定服务器名称。也不确定它是否返回与命令行相同的结果。

我尝试使用 ValidateCredentials 来检查使用我的凭据(使用 ContextType.Machine)是否通过了验证,但它没有返回 true 或 false,而是抛出 UnauthorizedAccessException。

【讨论】:

    【解决方案3】:

    我尝试在 .NET 中使用不同的方法访问 domino 服务器,但不幸的是,这个方法也不起作用。 (它抛出 DirectoryServicesCOMException(发生协议错误)。

            // create your "base" - the ou "formeremployees"
            DirectoryEntry formerEmployeeOU = new DirectoryEntry("LDAP://HOSTNAME");
    
            // create a searcher to find objects inside this container
            DirectorySearcher feSearcher = new DirectorySearcher(formerEmployeeOU);
    
            // define a standard ldap filter for what you search for - here "users"    
            feSearcher.Filter = "objectClass=*";
    
            // define the properties you want to have returned by the searcher
            feSearcher.PropertiesToLoad.Add("givenname");
            feSearcher.PropertiesToLoad.Add("sn");
            feSearcher.PropertiesToLoad.Add("mail");
            feSearcher.PropertiesToLoad.Add("memberOf");
    
            // search and iterate over results
            foreach (SearchResult sr in feSearcher.FindAll())
            {
                //do something
            }
    
            return;
    

    我的快速解决方案是运行 ldapsearch 命令行工具。

            // Start the child process.
            Process p = new Process();
            // Redirect the output stream of the child process.
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.RedirectStandardOutput = true;
            p.StartInfo.FileName = "ldapsearch";
            p.StartInfo.Arguments = "-L -h hostname \"objectClass=*\" givenname sn mail";
            p.Start();
            // Do not wait for the child process to exit before
            // reading to the end of its redirected stream.
            // p.WaitForExit();
            // Read the output stream first and then wait.
            string output = p.StandardOutput.ReadToEnd();
            p.WaitForExit();
    
            System.IO.File.WriteAllText(@"output.txt", output);
            return;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-14
      相关资源
      最近更新 更多