2010-09-30 11 views
10

मुझे एक स्ट्रिंग मिली है जो मैं सक्रिय निर्देशिका समूह सदस्यता के लिए एलडीएपी से ला रहा हूं और मुझे यह जांचने की आवश्यकता है कि उपयोगकर्ता एडी समूह का सदस्य है या नहीं। क्या कोई कक्षा है जो मेरे लिए इसे पार्स कर सकती है?क्या कोई .NET क्लास है जो एलडीएपी से सीएन = तारों को पार्स कर सकती है?

उदाहरण:

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

ध्वनि - रेगुलर एक्सप्रेशन से काम करना चाहिए ... –

+0

देखें http://stackoverflow.com/questions/356480/c-extracting-a-name-from-a-string – nos

+0

मैं RegEx का उपयोग नहीं करना चाहता क्योंकि मैं परीक्षण लागत नहीं लेना चाहता हूं। सुझाव के लिए धन्यवाद। –

उत्तर

4

यदि आप एक समूह के सदस्यों के लिए विज्ञापन क्वेरी, आप पार्स बिना सदस्यों की distinguishedName के सीधे के सभी तुलना करने के लिए सक्षम हो जाएगा:

CodeProject एक पार्सर परियोजना आपको क्या चाहिए करने के लिए प्रतीत होता है कि है System.DirectoryServices नामस्थान के माध्यम से कोड।

अन्यथा, मुझे कहीं ऐसी कक्षा के बारे में पता नहीं है। =)

उम्मीद है कि यह किसी भी तरह से मदद करता है!

संपादित करें # 1

यहाँ एक कड़ी है जहाँ से मैं एक बहुत विज्ञापन और System.DirectoryServices नाम स्थान के साथ काम सीखा है है: Howto: (Almost) Everything In Active Directory via C#

मैं कुछ ही दिनों में एक नमूना कोड के साथ आप प्रदान करेगा, यदि आपको अभी भी इसकी आवश्यकता है, तो मैं समूह के सदस्यों को पुनर्प्राप्त करने के लिए System.DirectoryServices.DirectorySearcher ऑब्जेक्ट क्लास का उपयोग करूंगा।

मुझे आशा है कि यह लिंक आपकी मदद करेगा जैसा कि उसने मेरे लिए किया था! =)

संपादित करें # 2

यहाँ कोड नमूना मैं बारे में बताया है। इसे एडी के खिलाफ बाक और काम करने के बिना एडी के खिलाफ पूछताछ करने के लिए और अधिक कुशल बनाना चाहिए।

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; 

} 

अस्वीकरण: इस कोड के रूप में है प्रदान की जाती है। मैंने इसे अपनी स्थानीय मशीन पर परीक्षण किया और यह पूरी तरह से ठीक काम करता है। लेकिन चूंकि मुझे इसे फिर से टाइप करना पड़ा क्योंकि मैं इसे कॉपी-पेस्ट नहीं कर सका, मैंने टाइपिंग करते समय शायद कुछ गलतियां की हैं, जो मेरी इच्छा नहीं थी।

+0

यह मेरे लिए बहुत अच्छा काम करता है, समस्या यह है कि यह एडी के साथ आगे और पीछे जाने वाली महंगी राउंड-ट्रिप लागत है। एक बार में सभी को लाने के लिए एक रास्ता कोशिश कर रहा है। –

+0

यदि आप .NET 3.5 का उपयोग कर रहे हैं या 'System.Linq' नेमस्पेस का उपयोग कर सकते हैं, तो हो सकता है कि आप शायद बार्ट डी स्मेट के LINQ को कोडप्लेक्स पर एडी प्रोजेक्ट पर नजर डालें। यह आपको एडी के खिलाफ पूछताछ के लिए LINQ का उपयोग करने की अनुमति देता है। दरअसल, लाइब्रेरी को पूरा करने के लिए कुछ काम करना है, लेकिन सबसे महत्वपूर्ण पहलुओं को उनके ओपन सोर्स कोड में शामिल किया गया है। –

+0

यदि आप किसी समूह के तत्काल सदस्य चाहते हैं, तो समूह के डीएन के खिलाफ 'निर्देशिका खोजकर्ता' पर कॉल करें और डीएन की सूची के लिए अपने 'सदस्यों की विशेषता' प्राप्त करें। यदि आप किसी समूह के समूहों के नेस्टेड सदस्यों को चाहते हैं, तो ऑब्जेक्ट एसआईडी की सूची के लिए 'टोकन समूह' विशेषता प्राप्त करें। मैंने इसके बारे में कुछ समय पहले लिखा था: http://explodingcoder.com/blog/content/how-query-active-directory-security-group-membership – spoulson

8

आप अतिरिक्त निर्भरता को जोड़ने के लिए नहीं करना चाहते हैं और सिर्फ स्ट्रिंग पार्स चाहते हैं ..

स्ट्रिंग के इस प्रकार आसानी से बस string.Split का उपयोग कर पार्स किया जा सकता। सीएन मान प्राप्त करने के लिए, कुछ ऐसा होगा ..

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]); 
} 
+0

+1 यह प्रश्न का उत्तर देता है और यह एक अच्छा समाधान है। –

+21

वापस पढ़ने वालों के लिए, यह समाधान उत्पादन वातावरण के लिए पर्याप्त नहीं है - [आरएफसी] (http://www.rfc-archive.org/getrfc.php?rfc=4514) निर्दिष्ट करता है कि मान उद्धृत किए जा सकते हैं और चरित्र से बचने वाले नियम भी हैं। इसके अलावा, इस प्रारूप के साथ अल्पविराम द्वारा स्ट्रिंग को विभाजित करना * अत्यधिक * खतरनाक है। –

6

इन्हें विशिष्ट नाम कहा जाता है। , इसके अलावा http://www.codeproject.com/KB/IP/dnparser.aspx

+0

इसे आसान पहुंच के लिए एक गीथब प्रोजेक्ट और न्यूज पैकेज में भी लपेटा गया है। https://github.com/picrap/DNParser/blob/master/README.md –

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

लेकिन ऐसा लगता है कि आप इसे गलत कर रहे हैं।सबसे पहले, अपने लक्षित समूह के लिए एसआईडी प्राप्त करें:

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); 

फिर, यह आपके पास निर्भर करता है कि यह आपके पास है। यदि उपयोगकर्ता आपका ऐप चला रहा है (या आपकी वेबसाइट/सेवा के लिए प्रमाणित), तो टोकन में एसआईडी का आकलन करें। उदाहरण के लिए, डेस्कटॉप ऐप्स में WindowsIdentity.GetCurrent().Groups का उपयोग करें। अन्यथा, आप spoulson तरह का सुझाव दिया है उपयोगकर्ता के लिए एक DirectoryEntry और फिर 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 
    } 
} 

बस मामले में आप एक सिड से एक 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(); 
} 
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); 
     } 
    } 
+0

बहुत बढ़िया - धन्यवाद दोस्त! –

+2

इस दृष्टिकोण की तरह काफी - हालांकि यह विशेषता नामों से व्हाइटस्पेस को ट्रिम नहीं करता है, और मुझे उद्धृत मानों के साथ कुछ समस्याएं भी शामिल हैं उदा। ओ = "वेरीसाइन, इंक" - इसलिए मैंने कुछ चीजें tweaked https://gist.github.com/davetransom/e9c58b96afa46d4c75a0 –

संबंधित मुद्दे

 संबंधित मुद्दे