Обещаю, это будет мой последний пост по этому вопросу. :)
После еще одной недели исследований и разработок у меня есть хорошее решение этой проблемы, и до сих пор оно работало для меня очень хорошо.
Подход несколько отличается от моего первого ответа, но в целом это та же концепция; используя 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);
Вот и все! Очень рад, что наконец-то это выяснилось.
Ваше здоровье!
person
X3074861X
schedule
09.11.2012