Angular 7中的Active Directory查找

时间:2018-12-11 11:23:07

标签: c# angular active-directory angular7

我正在使用角电抗形式的输入搜索字段来查找AD用户。因此,当您开始输入名称时,您将获得该字段的一些自动完成选项。为此,我从我的角度应用程序中调用了一个Web api方法,这反过来又向我返回了用户列表。我将该用户列表绑定到输入字段数据列表。我在Web API中使用以下代码:-

 public List<string> ADUsers()
 {
    List<string> users = new List<string>();  
    using (var context = new PrincipalContext(ContextType.Domain, "abc.in"))
    {
      using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
      {
         foreach (var result in searcher.FindAll())
         {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            if(de.Properties["givenName"].Value != null && de.Properties["sn"].Value != null)
              users.Add(de.Properties["givenName"].Value + " " + de.Properties["sn"].Value);
         }
       }
     }
     return users;
 }

由于用户数量太多,将列表返回到angular(20-25 secs)需要花费一些时间,而这又需要花费时间才能反映在反应形式输入字段中。我是无经验的,基本上是.net开发人员。您能否提出一些方法来找出一些响应式解决方案?或者是否有可能具有角度本身的功能,这样我就不应该为此调用web api方法?

2 个答案:

答案 0 :(得分:2)

我在您的代码中看到几个问题:

  1. 您没有过滤用户。因此,此代码每次运行时都会查找您域中的每个用户。您可以通过使用用户已经输入的文本作为过滤器,并限制返回的结果数来更改此设置(在自动完成控件中没有显示100多个名称的点)
  2. PrincipalSearcher和整个System.DirectoryServices.AccountManagement名称空间不是很有效。例如,在这种情况下,即使您仅使用名字和姓氏,它也会为在幕后找到的每个结果加载每个属性。通过直接使用System.DirectoryServices命名空间(DirectorySearcher / DirectoryEntry,无论如何,AccountManagement命名空间在幕后都可以使用),您可以做得更好。

以下是适合您的情况的示例:

public List<string> ADUsers(string filter) {
    if (string.IsNullOrEmpty(filter)) throw new ArgumentNullException(nameof(filter));

    List<string> users = new List<string>();
    var ds = new DirectorySearcher(
        new DirectoryEntry("LDAP://abc.in"), //domain to search
        $"(&(objectClass=user)(anr={filter}))", //search filter
        new[] { "givenName", "sn" }) //attributes to load
    {
        SizeLimit = 25 //change this depending on how many you want to show
    };

    using (var results = ds.FindAll()) {
        foreach (SearchResult result in results) {
            users.Add($"{result.Properties["givenName"][0]} {result.Properties["sn"][0]}");
        }
    }
    return users;
}

您可以将其任何部分名称作为filter传递给它,并且它使用AD中称为Ambiguous Name Resolution的功能来查找用户。这将在名字,姓氏和其他属性(该文档中的完整列表)中查找部分匹配项。

我也将结果限制为25,但是您可以根据需要更改它。

此方法还告诉AD 为每个结果返回givenNamesn属性,因为这就是我们关心的全部。这将减少您的应用程序与域控制器之间的网络流量。

答案 1 :(得分:0)

我在方法中也应用了过滤器,而且速度非常快。代码如下:-

public List<string> ADUsers(string filter)
{
    List<string> users = new List<string>();

    PrincipalContext domainContext = new PrincipalContext(ContextType.Domain, "abc.in");
    UserPrincipal user = new UserPrincipal(domainContext)
    {
        GivenName = filter + "*"
    };

    PrincipalSearcher pS = new PrincipalSearcher
    {
        QueryFilter = user
    };

    PrincipalSearchResult<Principal> results = pS.FindAll();
    List<Principal> pc = results.ToList();
    foreach (Principal p in pc)
    {
        DirectoryEntry de = (DirectoryEntry)p.GetUnderlyingObject();
        if (de.Properties["givenName"].Value != null && de.Properties["sn"].Value != null)
            users.Add(de.Properties["givenName"].Value + " " + de.Properties["sn"].Value);
    }

    return users;
}

我认为使用System.DirectoryServices.AccountManagement不会出现任何性能问题,并且对我来说效果很好。我仍然将加百列的答案标记为正确答案(应用过滤器的想法)。

相关问题