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

时间:2010-09-30 18:44:48

标签: .net active-directory ldap

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

示例:

CN=Foo Group Name,DC=mydomain,DC=com

7 个答案:

答案 0 :(得分: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]);
}

答案 1 :(得分:6)

这些被称为专有名称。

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

答案 2 :(得分:4)

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

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

希望无论如何都有帮助!

编辑#1

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

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

我希望这个链接对我有所帮助! =)

编辑#2

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

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;

}
  

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

答案 3 :(得分: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);
        }
    }

答案 4 :(得分: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();
    }
}

答案 5 :(得分:0)

要回答解析问题,请将PInvoke与DsGetRdnW一起使用。有关代码,请参阅我对其他问题的回答: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();
}

答案 6 :(得分:0)

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