Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 递归查询LDAP组成员资格_C#_Asp.net Mvc 3_Ldap - Fatal编程技术网

C# 递归查询LDAP组成员资格

C# 递归查询LDAP组成员资格,c#,asp.net-mvc-3,ldap,C#,Asp.net Mvc 3,Ldap,我正在编写一个基于MVC的(.NET 4.0)网站,它需要来自公司LDAP服务器的登录凭据。我的代码要求只允许属于某个组的用户。例如,我可能正在寻找属于“企业IT”组的用户。我的凭证可以是“系统管理员”组的一部分,该组是“公司IT”的一个子组。我正在使用表单身份验证 当用户登录时,我如何递归地检查他们属于哪个组?如果要检查特定用户的成员身份,请绑定到相关的AD对象并检索属性。它包含二进制形式的所有直接和间接组成员身份-它是一个字节数组数组。可以将每个字节数组传递给SecurityIdentifi

我正在编写一个基于MVC的(.NET 4.0)网站,它需要来自公司LDAP服务器的登录凭据。我的代码要求只允许属于某个组的用户。例如,我可能正在寻找属于“企业IT”组的用户。我的凭证可以是“系统管理员”组的一部分,该组是“公司IT”的一个子组。我正在使用表单身份验证


当用户登录时,我如何递归地检查他们属于哪个组?

如果要检查特定用户的成员身份,请绑定到相关的AD对象并检索属性。它包含二进制形式的所有直接和间接组成员身份-它是一个字节数组数组。可以将每个字节数组传递给SecurityIdentifier类的构造函数,然后将其转换为包含明文中组名称的NTAccount

var sids = new IdentityReferenceCollection();
foreach (byte[] group in tokenGroups)
{
    sids.Add(new SecurityIdentifier(group, 0));
}
var accounts = sids.Translate(typeof(NTAccount));

这里有一个完全不同的解决方案。在我的域名上测试和工作。注意:您必须获得DirectorySearcher.Filter正确。为您的广告层次结构添加多个OU(按相反顺序,自底向上)。另外请注意,为了安全起见,我在“使用”语句中处理了一些对象,因为它们实现了System.ComponentModel.Component,而System.ComponentModel.Component反过来又实现了IDisposable。。。所以,安全总比后悔好

public bool IsUserMemberOfGroup(string groupName)
    {
        // CN is your distro group name. OU is the object(s) in your AD hierarchy. DC is for your domain and domain suffix (e.g., yourDomain.local)
        string searchFilter = String.Format(@"(&(objectcategory=user)(sAMAccountName=markp)(memberof=CN={0},OU=System Admins,OU=USA,DC=yourDomain,DC=local))", groupName);
        SearchResultCollection searchResult;

        using (var dirEntry = new DirectoryEntry("LDAP://dc=yourDomain,dc=local"))
        {
            using (var dirSearch = new DirectorySearcher(dirEntry))
            {
                dirSearch.SearchScope = SearchScope.Subtree;
                dirSearch.Filter = searchFilter;
                searchResult = dirSearch.FindAll();
            }
        }
        if (searchResult.Count <= 0 || searchResult == null) {
            return false; // not in group
        }
        else {
            return true; // in group
        }
    }
public bool IsUserMemberOfGroup(字符串groupName)
{
//CN是您的发行组名称。OU是您的广告层次结构中的对象。DC是您的域和域后缀(例如,yourDomain.local)
string searchFilter=string.Format(@“(&(objectcategory=user)(sAMAccountName=markp)(memberof=CN={0},OU=System Admins,OU=USA,DC=yourDomain,DC=local)),groupName);
SearchResultCollection searchResult;
使用(var dirEntry=newdirectoryEntry(“LDAP://dc=yourDomain,dc=local”))
{
使用(var dirSearch=newdirectorysearcher(dirEntry))
{
dirSearch.SearchScope=SearchScope.Subtree;
dirSearch.Filter=searchFilter;
searchResult=dirSearch.FindAll();
}
}

如果(searchResult.Count对于搜索此类查询而来的任何其他人,我是如何在我的应用程序中执行此操作的:

关键是扩展搜索筛选器。由于此特定筛选器仅适用于DNs,我首先获取要检查的用户的DN,然后查询组,以查看此特定用户是否是链中任何组的成员

internal const string UserNameSearchFilter = "(&(objectCategory=user)(objectClass=user)(|(userPrincipalName={0})(samAccountName={0})))";
internal const string MembershipFilter = "(&(objectCategory=group)(objectClass=group)(cn=MyGroup)(member:1.2.840.113556.1.4.1941:={0}))";

using (var de = new DirectoryEntry(AppSettings.LDAPRootContainer, AppSettings.AdminUser, AppSettings.AdminPassword, AuthenticationTypes.FastBind))
using (var ds = new DirectorySearcher(de) { Filter = string.Format(UserNameSearchFilter, username) })
{

    ds.PropertiesToLoad.AddRange(new[] { "distinguishedName" });

    var user = ds.FindOne();

    if (user != null)
        using (var gds = new DirectorySearcher(de) { PropertyNamesOnly = true, Filter = string.Format(MembershipFilter, user.Properties["distinguishedName"][0] as string) })
        {
             gds.PropertiesToLoad.AddRange(new[] { "objectGuid" });
             return gds.FindOne() != null;
        }
}

我发现使用带有递归标志的
GroupPrincipal.GetMembers
是快速有效的

public bool IsMember(string groupName, string samAccountName)
{
    using (PrincipalContext context = new PrincipalContext(ContextType.Domain))
    using (UserPrincipal user = UserPrincipal.FindByIdentity(context, samAccountName))
    using(GroupPrincipal group = GroupPrincipal.FindByIdentity(context, groupName))
    {
        return group.GetMembers(true).OfType<Principal>().Any(u => u.SamAccountName.Equals(user.SamAccountName, StringComparison.InvariantCultureIgnoreCase));
    }

}
public bool IsMember(字符串groupName,字符串samAccountName)
{
使用(PrincipalContext上下文=新PrincipalContext(ContextType.Domain))
使用(UserPrincipal user=UserPrincipal.FindByIdentity(上下文,samAccountName))
使用(GroupPrincipal组=GroupPrincipal.FindByIdentity(上下文,组名))
{
return group.GetMembers(true).OfType().Any(u=>u.SamAccountName.Equals(user.SamAccountName,StringComparison.InvariantCultureIgnoreCase));
}
}

这项技术有效,但不包括通讯组列表,只包括安全组。如果有人知道如何获取通讯组列表,那就太好了。事实上,我正在寻找组枚举。包含通讯组的组枚举?根据MSDN,GetGroups方法不会执行组成员的递归查找bership,因此它不会返回间接的组成员身份。GetAuthorizationGroups可以进行递归查找,但仅限于安全组,就像我的方法一样。你说得对,Henning。很好。我想这个问题可能有些模糊。@MarkP想得更多,你实际上不需要查看/列出所有组,是吗?你只需要验证用户是否在某个特定(AD发行版)中组。对吗?如果是这样,那是可行的。否则,您将看到递归he*l,或者甚至调用PowerShell。是的,我只需要验证某个用户是否是更大组的一部分。@MarkP完全更改了答案。解决方案现在应该适合您了。@PatrickPitre-此新解决方案将只获得直接组成员身份,since您正在测试memberOf属性。