【问题标题】:Active directory lookup in Angular 7Angular 7 中的活动目录查找
【发布时间】:2018-12-12 00:17:47
【问题描述】:

我正在使用角度反应形式的输入搜索字段来查找 AD 用户。因此,当您开始输入您的姓名时,您应该获得该字段的一些自动完成选项。为此,我从我的 Angular 应用程序中调用了一个 web api 方法,该方法又返回给我一个用户列表。我将该用户列表绑定到输入字段数据列表。我在我的网络 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 秒) 需要时间,这反过来需要时间来反映在反应形式的输入字段中。我是 Angular 新手,基本上是 .net 开发人员。您能否提出一些方法来找出一些响应式解决方案?或者是否有可能在角度本身具有功能,以便我不应该为此调用 web api 方法?

【问题讨论】:

    标签: c# angular active-directory angular7


    【解决方案1】:

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

    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 属性,因为这就是我们所关心的。这将减少您的应用和域控制器之间的网络流量。

    【讨论】:

      【解决方案2】:

      我也完成了在我的方法中应用过滤器的方法,它非常快。代码如下:-

      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 不会有任何性能问题,它对我来说非常有效。我仍然将加布里埃尔的答案标记为正确答案(应用过滤器的想法)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多