【问题标题】:Search for Global Domain at Active Directory在 Active Directory 中搜索全局域
【发布时间】:2011-12-22 02:38:28
【问题描述】:

如果我有以下 AD 域路径:

AD 路径:

  • LDAP://AAA.CORP.XX.COM
  • LDAP://BBB.CORP.XX.COM
  • LDAP://CCC.BBB.CORP.XX.COM
  • LDAP://DDD.CORP.XX.COM
  • LDAP://EEE.CORP.XX.COM
  • LDAP://FFF.CORP.XX.COM

我需要在上述域中搜索用户是否存在于其中一个域中。

我目前的解决方案:

我遍历了上面的所有域,对于每个域,我检查用户是否存在,在上面的一个域中花费了 6-7 秒,其余的不到 1 秒。

提高性能的建议解决方案:

  1. 尝试在应为LDAP://CORP.XX.COM 的父域中搜索用户,这样将节省搜索次数,而不是每个域的 5 次搜索为 1 次搜索父域
  2. 尝试使用“全局目录”==>我需要 guid(C# 代码教程)

哪种解决方案更能提高性能问题?

【问题讨论】:

  • 你有什么代码..?您的连接 cn= dn= ect... 是什么样的...您是否正在创建 DirectorySearcher 对象...?同样在搜索用户时,您打算搜索/检查什么属性..? SAMAccount...等..
  • DirectoryEntry de = new DirectoryEntry() ; de.Path ="LDAP://AAA.CORP.XX.COM";搜索过滤器格式=(&(objectClass=user)(sAMAccountName={0}))
  • 等一下,让我看看我是否可以向您发送一些您将能够遵循的代码 sn-ps 给我 2 分钟确定 public String GetName(string username) 也适用于您..随心所欲地改变你喜欢我
  • 感谢 DJ,我通过了您的代码,但它似乎是根据域路径搜索用户。所以我仍然有同样的问题,我将搜索每个域,我的主要问题是我需要点击搜索 1 次而不是 5 次
  • 您应该也可以使用现有代码来处理其他事情。您是否尝试过获取任何属性并在 directoryEntry 变量中查看可用的内容.. entry 变量应该产生很多

标签: c# active-directory


【解决方案1】:

如果您使用的是 .NET 3.5 或更高版本,您应该能够使用 PrincipalSearcher 和“按示例查询”主体进行搜索:

// create your domain context
// here, you could also include a specific domain, if needed
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// define a "query-by-example" principal - here, we search for a UserPrincipal 
UserPrincipal qbeUser = new UserPrincipal(ctx);

// if you're looking for a particular user - you can limit the search by specifying
// e.g. a SAMAccountName, a first name - whatever criteria you are looking for
qbeUser.SamAccountName = "johndoe";

// create your principal searcher passing in the QBE principal    
PrincipalSearcher srch = new PrincipalSearcher(qbeUser);

// find all matches
foreach(var found in srch.FindAll())
{
    // do whatever here - "found" is of type "Principal" - it could be user, group, computer.....          
}

您可以在UserPrincipal 上指定任何属性,并将它们用作PrincipalSearcher 的“示例查询”。这比使用旧的 DirectorySearcher 方法要容易得多。

如果您还没有 - 一定要阅读 MSDN 文章 Managing Directory Security Principals in the .NET Framework 3.5,它很好地展示了如何充分利用 System.DirectoryServices.AccountManagement 中的新功能

【讨论】:

  • 谢谢marc_s:我错过了确定父域名的代码(我想在我的情况下应该是:CORP.XX.COM)我应该在principalContext()中传递这个名称吗????
  • @thabet084:我会尝试在不传递任何内容的情况下开始 - 只是为了看看你最终在哪里以及它首先搜索的位置。一旦启动并运行,然后开始使用传递各种 LDAP 路径作为起点。
  • 好点 Marc 我完全忘记了这一点。我个人非常习惯使用我发布的内容,因为 LDAP、AD 和我必须查询一次的 Java 工具之一现在看起来很熟悉,因为我看上下文大声笑我投票给你
【解决方案2】:

这是一个我在几个地方编写和使用的类,通过方法看看你可以使用什么..

using System;
using System.Text;
using System.Collections;
using System.DirectoryServices;
using System.Diagnostics;
using System.Data.Common;

namespace Vertex_VVIS.SourceCode
{
    public class LdapAuthentication
    {
        private String _path;
        private String _filterAttribute;

        public LdapAuthentication(String path)
        {
            _path = path;
        }
 public bool IsAuthenticated(String domain, String username, String pwd)
        {
            String domainAndUsername = domain + @"\" + username;
            DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);

            try
            {   //Bind to the native AdsObject to force authentication.         
              //  Object obj = entry.NativeObject;

                DirectorySearcher search = new DirectorySearcher(entry);

                search.Filter = "(SAMAccountName=" + username + ")";
                search.PropertiesToLoad.Add("cn");
                SearchResult result = search.FindOne();

                if (null == result)
                {
                    return false;
                }

                //Update the new path to the user in the directory.
                _path = result.Path;
                _filterAttribute = (String)result.Properties["cn"][0];
            }
            catch (Exception ex)
            {
                throw new Exception("Error authenticating user. " + ex.Message);
            }

            return true;
        }

        public String GetName(string username)
        {

            String thename = null;

            try
            {
                DirectoryEntry de = new DirectoryEntry(_path);
                DirectorySearcher ds = new DirectorySearcher(de);
                ds.Filter = String.Format("(SAMAccountName={0})", username);
                ds.PropertiesToLoad.Add("displayName");
                SearchResult result = ds.FindOne();
                if (result.Properties["displayName"].Count > 0)
                {
                    thename = result.Properties["displayName"][0].ToString();
                }
                else
                {
                    thename = "NA";
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error Getting Name. " + ex.Message);
            }

            return thename.ToString();
        }

        public String GetEmailAddress(string username)
        {
            String theaddress = null;
            try
            {
                DirectoryEntry de = new DirectoryEntry(_path);
                DirectorySearcher ds = new DirectorySearcher(de);
                ds.Filter = String.Format("(SAMAccountName={0})", username);
                ds.PropertiesToLoad.Add("mail");
                SearchResult result = ds.FindOne();
                theaddress = result.Properties["mail"][0].ToString();
                de.Close();
            }
            catch (Exception ex)
            {
                throw new Exception("Error Getting Email Address. " + ex.Message);
            }

            return theaddress.ToString();
        }
        public String GetTitle(string username)
        {
            String thetitle = null;
            try
            {
                DirectoryEntry de = new DirectoryEntry(_path);
                DirectorySearcher ds = new DirectorySearcher(de);
                ds.Filter = String.Format("(SAMAccountName={0})", username);
                ds.PropertiesToLoad.Add("title");
                SearchResult result = ds.FindOne();
                result.GetDirectoryEntry();
                if (result.Properties["title"].Count > 0)
                {
                    thetitle = result.Properties["title"][0].ToString();
                }
                else
                {
                    thetitle = "NA";
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error Getting the Title. " + ex.Message);
            }

            return thetitle.ToString();
        }

        public String GetPhone(string username)
        {
            String thephone = null;
            try
            {
                DirectoryEntry de = new DirectoryEntry(_path);
                DirectorySearcher ds = new DirectorySearcher(de);
                ds.Filter = String.Format("(SAMAccountName={0})", username);
                ds.PropertiesToLoad.Add("mobile");
                SearchResult result = ds.FindOne();
                result.GetDirectoryEntry();
                if (result.Properties["mobile"].Count > 0)
                {
                    thephone = result.Properties["mobile"][0].ToString();
                }
                else
                {
                    thephone = "NA";
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error Getting Phone Number. " + ex.Message);
            }

            return thephone.ToString();
        }

        public String GetGroups()
        {
            DirectorySearcher search = new DirectorySearcher(_path);
           search.Filter = "(cn=" + _filterAttribute + ")";
           search.PropertiesToLoad.Add("memberOf");
            StringBuilder groupNames = new StringBuilder();

            try
            {
                SearchResult result = search.FindOne();

                int propertyCount = result.Properties["memberOf"].Count;

                String dn;
                int equalsIndex, commaIndex;

                for (int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
                {
                    dn = (String)result.Properties["memberOf"][propertyCounter];

                    equalsIndex = dn.IndexOf("=", 1);
                    commaIndex = dn.IndexOf(",", 1);
                    if (-1 == equalsIndex)
                    {
                        return null;
                    }

                    groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1));
                    groupNames.Append("|");

                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error obtaining group names. " + ex.Message);
            }
            return groupNames.ToString();
        }

        public bool IsUserGroupMember(string strUserName, string strGroupString)
        {
            bool bMemberOf = false;
            ResultPropertyValueCollection rpvcResult = null; 
            try
            {
                DirectoryEntry de = new DirectoryEntry(_path);
                DirectorySearcher ds = new DirectorySearcher(de);
                ds.Filter = String.Format("(SAMAccountName={0})", strUserName);
                ds.PropertiesToLoad.Add("memberOf");
                SearchResult result = ds.FindOne();
                string propertyName = "memberOf";  
                rpvcResult = result.Properties[propertyName];  

                foreach (Object propertyValue in rpvcResult)  
                 {
                     if (propertyValue.ToString().ToUpper() == strGroupString.ToUpper())
                     {  
                         bMemberOf = true;
                         break;
                     }  
                 }  
            }
            catch (Exception ex)
            {
                throw new Exception("Error Getting member of. " + ex.Message);
            }

            return bMemberOf;

        }
    }
}

【讨论】:

  • 感谢 DJ,我通过了您的代码,但似乎是根据域路径搜索用户。所以我仍然有同样的问题,我将搜索每个域,我的主要问题是我需要点击搜索 1 次而不是 5 次 -
【解决方案3】:

我回答了一个类似的问题 (Can I match a user to a group accross different domains),答案与 @Marc_s 接近,但在答案的末尾,您可以看到该域的放置位置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2015-07-02
    • 1970-01-01
    相关资源
    最近更新 更多