wake-up-neo.net

System.DirectoryServices - Der Server ist nicht betriebsbereit

Ich erhalte eine Fehlermeldung von einer Website, auf der ich die Windows-Authentifizierung verwende.

Komische Dinge:

  • Tritt nur auf, wenn der Benutzer noch nicht in der Datenbank gespeichert ist (neuer unbekannter Benutzer)
  • Erscheint nur auf Live-Systemen, alles in Ordnung in der lokalen Entwicklungsumgebung

Folgendes erhalte ich in einer Logging-Mail:

Quelle: System.DirectoryServices

Meldung: Der Server ist nicht betriebsbereit.

Spur:
bei System.DirectoryServices.DirectoryEntry.Bind (Boolean throwIfFail)
bei System.DirectoryServices.DirectoryEntry.Bind ()
bei System.DirectoryServices.DirectoryEntry.get_AdsObject ()
bei System.DirectoryServices.DirectorySearcher.FindAll (Boolean findMoreThanOne)
bei System.DirectoryServices.DirectorySearcher.FindOne ()
bei Smarthouse.Labs.DataAccess.UserListManager.SaveUser (String windowsUserName)

So implementiere ich DirectorySearch:

private void SaveUser(string windowsUserName)
{
    string[] domainAndUser = windowsUserName.Split('\\');
    string domain = domainAndUser[0];
    string username = domainAndUser[1];

    DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain);
    DirectorySearcher search = new DirectorySearcher(entry);

    try
    {
        // Bind to the native AdsObject to force authentication.
        search.Filter = "(SAMAccountName=" + username + ")";
        search.PropertiesToLoad.Add("cn");
        search.PropertiesToLoad.Add("sn");
        search.PropertiesToLoad.Add("givenName");
        search.PropertiesToLoad.Add("mail");

        SearchResult result = search.FindOne();

        if (result == null)
        {
            throw new Exception("No results found in Windows authentication.");
        }

        User userToSave = new User();
        userToSave.FirstName = (String) result.Properties["givenName"][0];
        userToSave.LastName = (String) result.Properties["sn"][0];
        userToSave.Email = (String) result.Properties["mail"][0];
        userToSave.Username = windowsUserName;
        userToSave.Guid = Guid.NewGuid();

        SaveUser(userToSave);
    }
    catch (Exception ex)
    {
        throw new Exception("Error authenticating user. " + ex.Message, ex);
    }
    finally
    {
        //Dispose service and search to prevent leek in memory
        entry.Dispose();
        search.Dispose();
    }
}

Wenn weitere Codebeispiele benötigt werden, sagen Sie es mir einfach.

14
Tai Kahar

Ihr Problem ist, dass Sie zum Binden einen "normalen" Domainnamen verwenden - dies funktioniert in LDAP nicht. Wenn Sie versuchen, an LDAP://MyDomain zu binden, versuchen Sie tatsächlich , an den Server zu binden. ) genannt MyDomain.

Sie benötigen eine gültige LDAP-Bindungszeichenfolge - etwa LDAP://dc=yourdomain,dc=local oder so.

Verwenden Sie diesen Codeausschnitt, um den Standardkontext für die LDAP-Bindung zu ermitteln:

DirectoryEntry deRoot = new DirectoryEntry("LDAP://RootDSE");

if (deRoot != null)
{
   string defaultNamingContext = deRoot.Properties["defaultNamingContext"].Value.ToString();
}

Sobald Sie diese Zeichenfolge haben, verwenden Sie diese als Bindungszeichenfolge für Ihren LDAP-Server.

Wenn Sie .NET 3.5 oder höher verwenden, sollten Sie den Namespace System.DirectoryServices.AccountManagement (S.DS.AM) auschecken. Lesen Sie hier alles darüber:

Grundsätzlich können Sie einen Domänenkontext definieren und Benutzer und/oder Gruppen in AD leicht finden:

// set up domain context -- no domain name needed, uses default domain 
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, username);

if(user != null)
{
   // do something here....     
}

Das neue S.DS.AM macht es wirklich einfach, mit Benutzern und Gruppen in AD herumzuspielen!

19
marc_s

Um die Antwort von marc_s über zu ergänzen, musste ich mehrere Domains durchsuchen. Also habe ich für jede Domain folgendes gemacht:

DirectoryEntry deRoot = new DirectoryEntry("LDAP://" +"DomainName"+ "/RootDSE");
string defaultNamingContext = "LDAP://" + deRoot.Properties["defaultNamingContext"].Value.ToString();
DirectoryEntry mySearchRoot = new DirectoryEntry(defaultNamingContext);
DirectorySearcher myDirectorySearcher = new DirectorySearcher(mySearchRoot);
1
Claudio Viz

Ein ähnlicher Fehler ist mir aufgrund einer falschen Active Directory-Verbindungszeichenfolge passiert (obwohl dies die ganze Zeit passiert ist und nicht in bestimmten Fällen, auf die hier hingewiesen wird). ich habe das corp anstelle des prod verwendet. Verwenden Sie etwas, das für eine andere App in Ihrer Organisation funktioniert, sofern vorhanden.

0
boaz levinson

Sie können Bindungszeichenfolgen im Format LDAP: //meinedomäne.com: 389 verwenden. Ich habe immer wieder "Zugriff verweigert" erhalten, wenn ich versucht habe, das Format LDAP zu verwenden: // DC = meineDomäne, DC = com. Nachdem ich zum LDAP: //meinedomain.com: 389-Format gewechselt und beim Erstellen meines DirectoryEntry-Objekts das AuthenticationTypes.ServerBind-Flag verwendet habe, hat es hervorragend funktioniert. Dies war in Azure App Service.

0
r590