Получите дополнительные атрибуты Active Directory от Принципала вместо SearchResult DirectorySearcher - PullRequest
0 голосов
/ 24 сентября 2019

Я хотел бы получить некоторые дополнительные атрибуты AD от пользователя AD.Я хочу использовать PrincipalSearcher вместо DirectorySearcher.

То, что я сделал, - это получил underSearcher для PrincipalSearcher и вызвал метод FindOne ().Я не люблю использовать GetUnderlyingSearcher из PrincipalSearcher, но, очевидно, он работает.

Код работает, но мне интересно, есть ли способ прочитать дополнительные свойства / атрибуты объявлений из Principal

Principal match = principalSearcher.FindOne();

Кроме того, приведенный ниже код может иметь некоторые проблемы, потому что мы используем лежащие в основе методы (DirectorySearcher).

Я считаю PrincipalSearcher более высоким уровнем, а также, если бы я использовал DirectorySearcher, ldapPath должен быть определен e.g. var ldapPath = "DC=corp,DC=ad,DC=example,DC=com"; Это просто меньше строк кода.

public AdSimpleObject GetUser(string userName, string domainName)
{
  PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, domainName);

  UserPrincipal userPrincipal = new UserPrincipal(principalContext);
  userPrincipal.SamAccountName = userName; // where condition

  using (PrincipalSearcher principalSearcher = new PrincipalSearcher(userPrincipal))
  {
    using (DirectorySearcher ds = (DirectorySearcher)principalSearcher.GetUnderlyingSearcher())
    {
      // get only properties we need, therefore search performance is increased
      ds.PropertiesToLoad.Clear();
      ds.PropertiesToLoad.AddRange(new string[]
      {
        "sAMAccountType", 
        "sAMAccountName", 
        "userPrincipalName", 
        "msDS-PrincipalName"
      });

      SearchResult match = ds.FindOne();

      if (match != null)
      {
          AdSimpleObject ado = this.CreateAdSimpleObject(match);
          return ado;
      }  
      return null;
    }
  }
}

public class AdSimpleObject
{
  public string AdsPath { get; set; }
  public int SamAccountType { get; set; }
  public string SamAccountName { get; set; }
  public string MsDsPrincipalName { get; set; }
  public string UserPrincipalName { get; set; }
}

private AdSimpleObject CreateAdSimpleObject(SearchResult searchItem)
{
  ResultPropertyCollection props = searchItem.Properties;

  string adsPath = props["adspath"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
  int samAccountType = props["sAMAccountType"]?.OfType<int>().ToList().FirstOrDefault() ?? 0;
  string samAccountName = props["sAMAccountName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
  string userPrincipalName = props["userPrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;
  string msDsPrincipalName = props["msDS-PrincipalName"]?.OfType<string>().ToList().FirstOrDefault() ?? string.Empty;

  return new AdSimpleObject
  {
      AdsPath = adsPath,
      SamAccountType = samAccountType,
      SamAccountName = samAccountName,
      UserPrincipalName = userPrincipalName,
      MsDsPrincipalName = msDsPrincipalName
  };
}

1 Ответ

1 голос
/ 24 сентября 2019

Мне интересно, есть ли способ прочитать дополнительные свойства / атрибуты объявлений из Principal

Вы бы использовали возвращаемый объект DirectoryEntryс Principal.GetUnderlyingObject:

Principal match = principalSearcher.FindOne();
var de = (DirectoryEntry) match.GetUnderlyingObject();
de.RefreshCache(new string[] {"someAttribute"});
var someAttribute = de.Properties["someAttribute"].Value;

После этого вы вернетесь в AD, чтобы получить атрибуты, вместо использования данных, которые были получены при поиске.Использование RefreshCache состоит в том, чтобы указывать только те атрибуты, которые вас интересуют. Иначе, если вы сразу используете DirectoryEntry.Properties, он отправится в AD и получит все атрибуты, имеющие значение , что маловероятно, что вам нужно, и просто займет дополнительное время без причины.

Кроме того, в приведенном ниже коде могут возникнуть некоторые проблемы, поскольку мы используем лежащие в основе методы (DirectorySearcher).

Совсем нет.Этот код ничем не отличается от простого создания собственного DirectorySearcher и его использования.Фактически, с тем, как вы написали этот код, нет никакого смысла вообще использовать UserPrincipal / PrincipalSearcher.Единственное, что он для вас делает, это строит строку запроса.

Все пространство имен AccountManagement - это просто оболочка вокруг DirectoryEntry / DirectorySearcher.Это облегчает работу программиста (в некоторых случаях не всех), но делает это за счет производительности.

Если вы непосредственно используете DirectoryEntry / DirectorySearcher, у вас гораздо больше контролясколько данных извлекается из AD и как часто выполняются сетевые запросы.Те переводят на меньшее время.Если вы просто ищете одну учетную запись, это не будет иметь большого значения.Но если вы ищете большие группы пользователей или просматриваете большой список пользователей, это может иметь огромное значение.

Я написал статью об оптимизации производительности при общении с AD (особенно с * 1041).* / DirectorySearcher): Active Directory: лучшая производительность

...