是否有一个.NET类可以解析LDAP中的CN =字符串?

问题描述 投票:11回答:7

我有一个字符串,我从LDAP获取Active Directory组成员资格,我需要解析它以检查用户是否是AD组的成员。有没有可以解析这个问题的课程?

例:

CN=Foo Group Name,DC=mydomain,DC=com
.net active-directory ldap
7个回答
4
投票

此外,如果您查询AD的组成员,您将能够直接比较所有成员的distinguishedName,而无需通过DirectoryEntry命名空间的System.DirectoryServices类解析代码。

否则,我只是不知道某个地方的某个类。 =)

希望这无论如何都有帮助!

编辑#1

这是我从AD和System.DirectoryServices名称空间学习了很多东西的链接:Howto: (Almost) Everything In Active Directory via C#

我将在几天内为您提供示例代码,如果您仍然需要它,我将使用System.DirectoryServices.DirectorySearcher对象类来检索组的成员。

我希望这个链接可以帮助你,就像它对我一样! =)

编辑#2

这是我告诉你的代码示例。这样可以更有效地查询AD,而无需在AD上执行bakc。

public IList<string> GetMembers(string groupName) {
    if (string.IsNullOrEmpty(groupName))
        throw new ArgumentNullException("groupName");

    IList<string> members = new List<string>();

    DirectoryEntry root = new DirectoryEntry(@"LDAP://my.domain.com");
    DirectorySearcher searcher = new DirectorySearcher();
    searcher.SearchRoot = root;
    searcher.SearchScope = SearchScope.Subtree;
    searcher.PropertiesToLoad.Add("member");

    searcher.Filter = string.Format("(&(objectClass=group)(sAMAccountName={0}))", groupName);

    SearchResult result = searcher.FindOne();
    DirectoryEntry groupFound = result.GetDirectoryEntry();
    for (int index = 0; index < ((object[])groupFound.Properties["member"].Value).Length; ++index)
        members.Add((string)((object[])groupFound.Properties["member"].Value)[index]);

    return members;

}

免责声明:此代码按原样提供。我在我的本地机器上进行了测试,效果非常好。但是因为我不得不在这里重新输入它,因为我不能只是复制粘贴它,我可能在输入时犯了一些错误,我希望不会发生这种错误。


7
投票

如果您不想添加其他依赖项,只想解析字符串..

只需使用string.Split就可以轻松解析这种类型的字符串。要获得CN值,将会是......

string[] split = "CN=Foo Group Name,DC=mydomain,DC=com".Split(',');
List<string> cnValues = new List<string>();
foreach(string pair in split){
    string[] keyValue=pair.Split('=');
    if(keyValue[0]=="CN")
       cnValues.Add(keyValue[1]);
}

6
投票

这些被称为专有名称。

CodeProject有一个解析器项目,可以满足您的需求:http://www.codeproject.com/KB/IP/dnparser.aspx


3
投票

要解析DistinquishedName,您必须注意转义字符。这是一个正确解析字符串并返回键值对列表的方法。

    public static List<KeyValuePair<string, string>> ParseDistinguishedName(string input)
    {
        int i = 0;
        int a = 0;
        int v = 0;
        var attribute = new char[50];
        var value = new char[200];
        var inAttribute = true;
        string attributeString, valueString;
        var names = new List<KeyValuePair<string, string>>();

        while (i < input.Length)
        {
            char ch = input[i++];
            switch(ch)
            {
                case '\\':
                    value[v++] = ch;
                    value[v++] = input[i++];
                    break;
                case '=':
                    inAttribute = false;
                    break;
                case ',':
                    inAttribute = true;
                    attributeString = new string(attribute).Substring(0, a);
                    valueString = new string(value).Substring(0, v);
                    names.Add(new KeyValuePair<string, string>(attributeString, valueString));
                    a = v = 0;
                    break;
                default:
                    if (inAttribute)
                    {
                        attribute[a++] = ch;
                    }
                    else
                    {
                        value[v++] = ch;
                    }
                    break;
            }
        }

        attributeString = new string(attribute).Substring(0, a);
        valueString = new string(value).Substring(0, v);
        names.Add(new KeyValuePair<string, string>(attributeString, valueString));
        return names;
    }

    static void Main(string[] args)
    {
        const string TestString = "CN=BY2STRAKRJOB2,OU=MSNStorage,OU=RESOURCE,OU=PRODUCTION,DC=phx,DC=gbl,STREET=street address,L=locality Name,C=Country Name,UID=user id,STUFF=\\,\\.\\+\"<>;\\=\\0A";

        var names = ParseDistinguishedName(TestString);
        foreach (var pair in names)
        {
            Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
        }
    }

2
投票
Using System.DirectoryServices;

namespace GetGroups
{
    public string GetGroupName(string LDAPGroupEntry)
    {
        // LDAPGroupEntry is in the form "LDAP://CN=Foo Group Name,DC=mydomain,DC=com"
        DirectoryEntry grp = new DirectoryEntry(LDAPGroupEntry);
        return grp.Properties["Name"].Value.ToString();
    }
}

0
投票

要回答解析问题,请使用带有DsGetRdnW的PInvoke。有关代码,请参阅我对另一个问题的回答:https://stackoverflow.com/a/11091804/628981

但听起来你做错了。首先,获取目标组的SID:

string targetGroupName = //target group name;
DirectorySearcher dsTargetGroup = new DirectorySearcher();
dsTargetGroup.Filter = string.Format("(sAMAccountName={0})", targetGroupName);
SearchResult srTargetGroup = dsTargetGroup.FindOne();
DirectoryEntry deTargetGroup = srTargetGroup.GetDirectoryEntry();
byte[] byteSid = (byte[])deTargetGroup.Properties["objectSid"].Value;
SecurityIdentifier targetGroupSid = new SecurityIdentifier(byteSid, 0);

那么,这取决于你拥有什么。如果用户正在运行您的应用程序(或通过您的网站/服务进行身份验证),则枚举令牌中的SID。例如,在桌面应用程序中使用WindowsIdentity.GetCurrent().Groups。否则,您需要为该用户获取DirectoryEntry,然后获取像spoulson建议的tokenAttributes属性:

DirectoryEntry deTargetUser = //target user;
DirectorySearcher dsTargetUser = new DirectorySearcher(deTargetUser);
dsTargetUser.SearchScope = SearchScope.Base; //tokenGroups is a constructed attribute, so have to ask for it while performing a search
dsTargetUser.Filter = "(objectClass=*)"; //this is closest thing I can find to an always true filter
dsTargetUser.PropertiesToLoad.Add("tokenGroups");
SearchResult srTargetUser = dsTargetUser.FindOne();
foreach(byte[] byteGroupSid in srTargetUser.Properties["tokenGroups"])
{
    SecurityIdentifier groupSid = new SecurityIdentifier(byteGroupSid, 0);
    if(groupSid == targetGroupSid)
    {
        //success
    }
}

如果您需要从SID获取DirectoryEntry,您可以通过以下方式获取搜索字符串:

public static string GetSIDSearchFilter(SecurityIdentifier sid)
{
    byte[] byteSid = new byte[sid.BinaryLength];
    sid.GetBinaryForm(byteSid, 0);
    return string.Format("(objectSid={0})", BuildFilterOctetString(byteSid));
}

public static string BuildFilterOctetString(byte[] bytes)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < bytes.Length; i++)
    {
        sb.AppendFormat("\\{0}", bytes[i].ToString("X2"));
    }
    return sb.ToString();
}

0
投票

我来到这里看看我们是否可以将“LDAP://ldap.company.com:389 / ou = people,o = company”解析为协议,端口,baseDN和服务器FQDN。我尝试了System.Uri类它作为例外工作。

© www.soinside.com 2019 - 2024. All rights reserved.