在Active Directory中搜索全局域

时间:2011-12-20 20:07:23

标签: c# active-directory

如果我有以下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#代码教程)
  3. 哪种解决方案更能增强性能问题?

3 个答案:

答案 0 :(得分:2)

如果您使用的是.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

中的新功能

答案 1 :(得分:0)

这是我在几个地方编写和使用的类,通过方法查看可以使用的内容..

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;

        }
    }
}

答案 2 :(得分:0)

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