Obiecuję, to będzie mój ostatni wpis na to konkretne pytanie. :)
Po kolejnym tygodniu badań i rozwoju, mam na to dobre rozwiązanie, które jak dotąd sprawdziło się bardzo dobrze.
Podejście różni się nieco od mojej pierwszej odpowiedzi, ale generalnie jest to ta sama koncepcja; użycie LdapConnection do wymuszenia sprawdzenia poprawności certyfikatu.
//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];
Drugą rzeczą, jaką chciałem zwrócić uwagę jest to, że SearchResultEntry powróci użytkownika „atrybuty” zamiast „Właściwości”.
Atrybuty są zwracane jako tablice bajtów, więc musisz je kodować, aby uzyskać reprezentację ciągów. Na szczęście System.Text.Encoding zawiera natywną klasę ASCIIEncoding, która może sobie z tym poradzić bardzo łatwo.
string PropValue = ASCIIEncoding.ASCII.GetString(PropertyValueByteArray);
I o to chodzi! Bardzo szczęśliwy, że w końcu udało się to ustalić.
Pozdrawiam!
Cześć. Dzięki za wejście, bardzo docenione. Doszedłem również do wniosku, że cały problem można rozwiązać w bardziej niezawodny sposób, korzystając z przestrzeni nazw protokołów niższego poziomu. Zauważyłem, że gdy certyfikat z podpisem własnym jest poprawnie dodany do lokalnego magazynu certyfikatów komputera, mogę ustawić wywołanie zwrotne VerifyServerCertificate w celu sprawdzenia certyfikatu z powodzeniem, coś w stylu "delegate" (połączenie LdapConnection, certyfikat certyfikatu X509) {return new X509Certificate2 (certyfikat) .Verify()} ", ale nadal nie mam radości z DirectoryEntry. – Andrew
Zauważyłem również, że podczas zdarzeń w usłudze SystemEntry wystąpiły następujące zdarzenia systemowe: "Certyfikat odebrany z serwera zdalnego nie zawiera oczekiwanej nazwy, dlatego nie można ustalić, czy nawiązujemy połączenie z odpowiednim serwerem. Nazwa serwera, którego się spodziewaliśmy, to MYSERVER.MYDOMAIN.CO.UK. Żądanie połączenia SSL nie powiodło się. Załączone dane zawierają certyfikat serwera. " Zajmę się tym teraz, ale myślę, że odpowiedź wciąż jest obszarem nazw protokołów dla maksymalnej pewności i zmniejszonej zależności środowiskowej. – Andrew
Andrew, dzięki za komentarz. Wygląda na to, że pracujemy nad bardzo podobnym celem. Ten błąd, który widzisz w zdarzeniach systemowych, pokrywa się z wieloma informacjami, które przeczytałem w Internecie, dotyczącymi tego, komu wydano certyfikat. Wiele serwerów, na których działa protokół SSL, z którymi próbuję nawiązać interakcję, ma certyfikat wydany dla innej domeny niż ta, do której przyłączam się w LdapConnection ... a to z pewnością powoduje awarię DirectoryEntry. – X3074861X