如何检查用户是属于AD组还是嵌套组?

时间:2010-04-21 02:34:47

标签: .net asp.net active-directory windows-authentication

我有一个使用Windows身份验证的ASP.NET 3.5应用程序并实现了我们自己的RoleProvider。

问题是我们想要将对一组页面的访问限制为几千个用户,而不是逐个输入所有这些页面,我们发现它们属于一个AD组。

如果我们检查针对特定用户的成员资格的公共组是其直接成员,答案很简单但我遇到的问题是,如果该组是另一个组的成员,然后是另一个组的成员那么我的代码总是返回false。

例如:假设我们要检查用户是否是 E 组的成员,但用户不是*的直接成员E“,她是”A“的成员,”B“的成员确实是 E 的成员,因此用户是* E”的成员< / p>

我们所拥有的解决方案之一非常缓慢,尽管它给出了正确答案

using (var context = new PrincipalContext(ContextType.Domain))
  {
    using (var group = GroupPrincipal.FindByIdentity(context, IdentityType.Name, "DL-COOL-USERS"))
    {
      var users = group.GetMembers(true); // recursively enumerate

      return users.Any(a => a.Name == "userName");
    }
  }

原始解决方案以及我尝试使用.NET 3.5 System.DirectoryServices.AccountManagement工作,当用户是相关组的直接成员时,它确实有效,如下所示:

public bool IsUserInGroup(string userName, string groupName)
{
  var cxt = new PrincipalContext(ContextType.Domain, "DOMAIN");
  var user = UserPrincipal.FindByIdentity(cxt, IdentityType.SamAccountName, userName);

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


  var group = GroupPrincipal.FindByIdentity(cxt, groupName);

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

  return user.IsMemberOf(group);
}

最重要的是,我们需要检查成员资格,即使这些组在多个级别中嵌套。

非常感谢!

2 个答案:

答案 0 :(得分:1)

解决方案1:使用web.config限制访问

由于您使用的是ASP.NET,因此限制访问的更简单的解决方案是在web.config中设置它,示例如下:

<configuration>
  <location path="protected/url/path">
    <system.web>
      <authorization>
        <allow roles="DOMAIN\group"/>
        <deny users="*"/>
      </authorization>
    </system.web>
  </location>
</configuration>

有关详细信息:http://msdn.microsoft.com/en-us/library/wce3kxhd.aspxhttp://msdn.microsoft.com/en-us/library/b6x6shw7.aspx

解决方案2:更快地实现IsUserInGroup

我在.NET 2.0应用程序中使用的代码,在与您相似的大森林中运行良好。

static bool IsUserInGroup(DirectoryEntry user, string groupName)
{
    user.RefreshCache(new string[] {"tokenGroups"});
    for (int i = 0; i < user.Properties["tokenGroups"].Count; i++) {
        SecurityIdentifier sid = new SecurityIdentifier((byte[]) user.Properties["tokenGroups"][i], 0);
        try {
            NTuser nt = (NTuser) sid.Translate(typeof(NTuser));
            if (nt.Value.ToLower().EndsWith("\\" + groupName.ToLower())) {
                return true;
            }
        } catch (IdentityNotMappedException) {
            continue;
        }
    }

    return false;
}

答案 1 :(得分:1)

好吧,我不得不在广场外思考这个,幸运的是,通过调查AD我们发现所有3000多个必须看到页面的人在自定义AD属性中共享一个关键字。所以我所要做的就是从AD加载对象并查看它。最终结果客户非常高兴!目前这似乎是一个肮脏的解决方案,但一如既往,这是完美的工作,我们必须继续其他事情!

目前我们正在通过试点计划和我们得到的任何错误,我们希望它们冒出来并得到通知,以便我们采取行动。

public static bool IsEmployeeCoolEnoughToSeePages(string userName)
{
  if (string.IsNullOrEmpty(userName))
  {
    throw new ArgumentNullException("Current user's Username cannot be null");
  }

  using (var searcher = new DirectorySearcher(("LDAP://YOURDOMAIN.com")))
  {
    searcher.Filter = string.Format("(&(objectCategory=user)(samAccountName={0}))", ariseUserName);
    SearchResultCollection searchResultCollection = searcher.FindAll();

    if (searchResultCollection.Count == 1)
    {
      var values = searchResultCollection[0].Properties["title"];

      if (values.Count == 1)
      {
        return values[0].ToString().StartsWith("_COOLNES_");
      }
    }

    return false;
  }
}