2012-10-16 9 views
5

मेरे पास सामान्य सिस्टम का उपयोग कर निर्देशिका सेवा से डेटा की प्रतिलिपि बनाने का एक एप्लिकेशन है। डायरेक्टरी सर्विसेज। डायरेक्टरी एंटर्री कोड। अब मुझे एक स्वयं हस्ताक्षरित प्रमाणपत्र के साथ एसएसएल का उपयोग करते हुए नोवेल ई-डायरेक्टरी से दोहराने की आवश्यकता है। मुझे संदेह है कि मौजूदा कोड एक मान्य प्रमाणपत्र के साथ काम करेगा जिसे सत्यापित किया जा सकता है, या शायद यदि स्थानीय मशीन कीस्टोर में स्वयं हस्ताक्षरित प्रमाणपत्र जोड़ा जाता है। एक स्व-हस्ताक्षरित प्रमाण पत्र के साथ यह सुनिश्चित करने के लिए, एकमात्र समाधान जो मैं पा सकता हूं वह सिस्टम का उपयोग करना है। डायरेक्टरी सर्विसेज। प्रोटोकॉल नामस्थान और LdapConnection क्लास, जिससे मैं VerifyServerCertificate कॉलबैक को तार कर सकता हूं। मुझे एक निर्देशिका अवधारणा उदाहरण के लिए एक ही अवधारणा को लागू करने का कोई तरीका नहीं मिल रहा है, या किसी LdapConnection इंस्टेंस के साथ कनेक्ट करने और किसी भी तरह से "कनवर्टिंग" को DirectoryEntry उदाहरण में नहीं मिला है। शायद यह संभव नहीं है, मैं बस वास्तव में पुष्टि करना चाहता हूं। कोई अन्य विचार स्वागत है। http://www.codeproject.com/Articles/19097/eDirectory-Authentication-using-LdapConnection-andस्वत: हस्ताक्षरित SSL प्रमाणपत्र को संभालने के लिए System.DirectoryServices.DirectoryEntry के लिए कॉलबैक सेट करें?

उत्तर

8

यह एक अभूतपूर्व सवाल यह है:

केवल प्रासंगिक लिंक मैंने पाया है।

मैं कुछ दिनों के लिए इस मुद्दे को जूझ रहा हूं, और अंततः मुझे कुछ निश्चित सबूत मिल गया है कि निर्देशिका परिदृश्य ऑब्जेक्ट इस परिदृश्य में क्यों काम नहीं करेगा।

यह विशेष एलडीएपी सर्वर (एलडीएपीएस 636 पर चल रहा है) भी अपने स्वयं के हस्ताक्षरित प्रमाण पत्र को जारी करता है। LdapConnection का उपयोग करना (और Wireshark के माध्यम से ट्रैफिक की निगरानी), मैं एक हाथ मिलाना जगह है कि जब DirectoryEntry का उपयोग कर नहीं होती लेने देखा:

enter image description here

पहले अनुक्रम है सुरक्षित LDAP सर्वर से, दूसरी अनुक्रम से है मेरी मशीन कोड है कि दूसरी अनुक्रम संकेत देता है:

ldapConnection.SessionOptions.VerifyServerCertificate += delegate { return true; }; 

दूसरों के साथ वैसा करने के लिए कॉलबैक "बाहर नकली" कर रहे हैं, लेकिन यह मैं क्या उपयोग कर रहे हैं।

दुर्भाग्यवश, निर्देशिका एंट्री के पास स्वयं हस्ताक्षरित प्रमाण सत्यापित करने का कोई विकल्प या विधि नहीं है, इस प्रकार प्रमाण पत्र की स्वीकृति कभी नहीं होती (दूसरा अनुक्रम), और कनेक्शन प्रारंभ करने में विफल रहता है।

इसे पूरा करने का एकमात्र व्यवहार्य तरीका LdapConnection का उपयोग करके, SearchRequest और SearchResponse के संयोजन के साथ है। यह मैं अब तक क्या मिल गया है है:

LdapConnection ldapConnection = new LdapConnection("xxx.xxx.xxx:636"); 

var networkCredential = new NetworkCredential("Hey", "There", "Guy"); 
ldapConnection.SessionOptions.SecureSocketLayer = true; 
ldapConnection.SessionOptions.VerifyServerCertificate += delegate { return true; }; 
ldapConnection.AuthType = AuthType.Negotiate; 
ldapConnection.Bind(networkCredential); 

SearchRequest request = new SearchRequest("DC=xxx,DC=xxx,DC=xxx", "(sAMAccountName=3074861)", SearchScope.Subtree); 
SearchResponse response = (SearchResponse)ldapConnection.SendRequest(request); 

if(response.Entries.Count == 1) 
{SearchResultEntry entry = response.Entries[0]; 
string DN = entry.DistinguishedName;} 

वहां से आप तदनुसार SearchResponse से ई गुण, और इस प्रक्रिया इकट्ठा कर सकते हैं। यद्यपि यह कुल बमर है, क्योंकि SearchRequest निर्देशिका धीमी गति से उपयोग करने के बाद बहुत धीमी प्रतीत होता है।

आशा है कि इससे मदद मिलती है!

+0

हाय। उत्पादक सामग्री के लिए धन्यवाद, काफी सराहा। मैं इस निष्कर्ष पर भी आ रहा हूं कि निचले स्तर के प्रोटोकॉल नामस्थान का उपयोग करके पूरी समस्या को और अधिक भरोसेमंद तरीके से निपटाया जा सकता है। मैंने जो देखा है वह यह है कि जब स्वत: हस्ताक्षरित प्रमाणपत्र स्थानीय मशीन सर्टिफिकेट स्टोर में सही ढंग से जोड़ा जाता है, तो मैं सफलता के साथ प्रमाणपत्र को प्रमाणित करने के लिए VerifyServerCertificate कॉलबैक सेट कर सकता हूं, जैसे "प्रतिनिधि (LdapConnection कनेक्शन, X509 प्रमाण पत्र प्रमाणपत्र) {वापसी नया X509Certificate2 (सर्टिफिकेट)। सत्यापित करें()} ", लेकिन मुझे अभी भी DirectoryEntry के साथ कोई खुशी नहीं है। – Andrew

+0

मैंने यह भी देखा है कि असफल निर्देशिका एंटर्री प्रयासों के दौरान मुझे अपने सिस्टम इवेंट में निम्न मिलता है: "दूरस्थ सर्वर से प्राप्त प्रमाणपत्र में अपेक्षित नाम नहीं है। इसलिए यह निर्धारित करना संभव नहीं है कि हम सही सर्वर से कनेक्ट हैं या नहीं। जिस सर्वर का नाम हम उम्मीद कर रहे थे वह है MYSERVER.MYDOMAIN.CO.UK। SSL कनेक्शन अनुरोध विफल हो गया है। संलग्न डेटा में सर्वर प्रमाणपत्र शामिल है। " मैं अब उसमें देख रहा हूं, लेकिन मुझे लगता है कि जवाब अभी भी अधिकतम आत्मविश्वास और पर्यावरण निर्भरता को कम करने के लिए प्रोटोकॉल नामस्थान है। – Andrew

+0

एंड्रयू, टिप्पणी के लिए धन्यवाद। ऐसा लगता है कि हम एक बहुत ही समान लक्ष्य की ओर काम कर रहे हैं। सिस्टम इवेंट में जो त्रुटि आप देख रहे हैं, वह नेट पर पढ़ी गई बहुत सारी जानकारी के साथ मेल खाता है जो प्रमाण पत्र जारी किया जाता है। एसएसएल चलाने वाले सर्वरों में से कई सर्वर जिनके साथ मैं बातचीत करने की कोशिश कर रहा हूं, एक प्रमाण है जो एक अलग डोमेन को जारी किया गया है जिसे मैं LdapConnection में बाध्यकारी कर रहा हूं ... और यह निश्चित रूप से निर्देशिका एंटर्री विफल होने का कारण बनता है। – X3074861X

2

मैं वादा करता हूं, यह इस विशेष प्रश्न पर मेरी आखिरी पोस्ट होगी। :)

अनुसंधान और विकास के एक और सप्ताह के बाद, मेरे पास इसका अच्छा समाधान है, और इसने अब तक मेरे लिए बहुत अच्छा काम किया है।

दृष्टिकोण मेरा पहला उत्तर तो कुछ अलग है, लेकिन आम तौर पर, यह वही अवधारणा है; प्रमाण पत्र की पुष्टि को बल देने के लिए LdapConnection का उपयोग करना।

//I set my Domain, Filter, and Root-AutoDiscovery variables from the config file 
string Domain = config.LdapAuth.LdapDomain; 
string Filter = config.LdapAuth.LdapFilter; 
bool AutoRootDiscovery = Convert.ToBoolean(config.LdapAuth.LdapAutoRootDiscovery); 

//I start off by defining a string array for the attributes I want 
//to retrieve for the user, this is also defined in a config file. 
string[] AttributeList = config.LdapAuth.LdapPropertyList.Split('|'); 

//Delcare your Network Credential with Username, Password, and the Domain 
var credentials = new NetworkCredential(Username, Password, Domain); 

//Here I create my directory identifier and connection, since I'm working 
//with a host address, I set the 3rd parameter (IsFQDNS) to false 
var ldapidentifier = new LdapDirectoryIdentifier(ServerName, Port, false, false); 
var ldapconn = new LdapConnection(ldapidentifier, credentials); 

//This is still very important if the server has a self signed cert, a certificate 
//that has an invalid cert path, or hasn't been issued by a root certificate authority. 
ldapconn.SessionOptions.VerifyServerCertificate += delegate { return true; }; 

//I use a boolean to toggle weather or not I want to automatically find and query the absolute root. 
//If not, I'll just use the Domain value we already have from the config. 
if (AutoRootDiscovery) 
{ 
    var getRootRequest = new SearchRequest(string.Empty, "objectClass=*", SearchScope.Base, "rootDomainNamingContext"); 
    var rootResponse = (SearchResponse)ldapconn.SendRequest(getRootRequest); 
    Domain = rootResponse.Entries[0].Attributes["rootDomainNamingContext"][0].ToString(); 
} 

//This is the filter I've been using : (&(objectCategory=person)(objectClass=user)(&(sAMAccountName={{UserName}}))) 
string ldapFilter = Filter.Replace("{{UserName}}", UserName); 

//Now we can start building our search request 
var getUserRequest = new SearchRequest(Domain, ldapFilter, SearchScope.Subtree, AttributeList); 

//I only want one entry, so I set the size limit to one 
getUserRequest.SizeLimit = 1; 

//This is absolutely crucial in getting the request speed we need (milliseconds), as 
//setting the DomainScope will suppress any refferal creation from happening during the search 
SearchOptionsControl SearchControl = new SearchOptionsControl(SearchOption.DomainScope); 
getUserRequest.Controls.Add(SearchControl); 

//This happens incredibly fast, even with massive Active Directory structures 
var userResponse = (SearchResponse)ldapconn.SendRequest(getUserRequest); 

//Now, I have an object that operates very similarly to DirectoryEntry, mission accomplished 
SearchResultEntry ResultEntry = userResponse.Entries[0]; 

दूसरी बात मैं यहाँ नोट करने के लिए करना चाहता था कि SearchResultEntry उपयोगकर्ता वापस आ जाएगी "गुण" के बदले "गुण" है।

गुण बाइट एरे के रूप में लौटाए जाते हैं, इसलिए आपको स्ट्रिंग प्रस्तुति प्राप्त करने के लिए उनको एन्कोड करना होगा। शुक्र है, System.Text.Encoding में एक मूल ASCIIEncoding क्लास है जो इसे बहुत आसानी से संभाल सकता है।

string PropValue = ASCIIEncoding.ASCII.GetString(PropertyValueByteArray); 

और यह इसके बारे में है! आखिर में यह बहुत खुश है कि यह पता चला है।

चीयर्स!

+0

इसके लिए धन्यवाद, मैंने अंत में System.DirectoryServices.Protocols असेंबली का उपयोग करने के लिए पुन: इंजीनियर करने का भी निर्णय लिया। यह माना जाता है कि यह थोड़ा प्रक्रियात्मक है लेकिन धातु के बहुत करीब महसूस करने से पहले Win32 LDAP लाइब्रेरी के साथ काम किया है। और मुझे और अधिक आत्मविश्वास महसूस होता है कि कोड ADSI- आधारित सिस्टम का उपयोग कर कोड की तुलना में भविष्य की आवश्यकताओं के अनुकूल होगा। डायरेक्टरी सर्विसेज। – Andrew

0

मैंने DirectoryEntry का उपयोग करके ldaps से कनेक्ट करने के लिए कोड नीचे उपयोग किया है।

क्या मैं अपने scenerio में समझ में आ directoryEntry जब ldaps सर्वर पथ या प्रमाणीकरण प्रकार में निर्दिष्ट किया जाता के रूप में "AuthenticationTypes.SecureSocketsLayer" बताया गया है काम नहीं करता है, लेकिन यदि केवल ldaps बंदरगाह सर्वर नाम यह काम के अंत में उल्लेख किया गया है । वायरशर्क लॉग देखने के बाद मैं ऊपर पोस्ट में उल्लिखित हैंडशेक लेने के स्थान देख सकता हूं।

सहभागिता: enter image description here

कोड:

public static SearchResultCollection GetADUsers() 
    { 
     try 
     { 
      List<Users> lstADUsers = new List<Users>(); 
      DirectoryEntry searchRoot = new DirectoryEntry("LDAP://adserver.local:636", "username", "password"); 
      DirectorySearcher search = new DirectorySearcher(searchRoot); 
      search.PropertiesToLoad.Add("samaccountname"); 
      SearchResult result; 
      SearchResultCollection resultCol = search.FindAll(); 
      Console.WriteLine("Record count " + resultCol.Count); 
      return resultCol; 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("exception" + ex.Message); 
      return null; 
     } 
    } 
संबंधित मुद्दे