595 Stimmen

Einen Benutzernamen und ein Passwort gegen Active Directory validieren?

Wie kann ich einen Benutzernamen und ein Passwort mit Active Directory abgleichen? Ich möchte einfach prüfen, ob ein Benutzername und ein Kennwort korrekt sind.

23voto

stephbu Punkte 5051

Der wahrscheinlich einfachste Weg ist der PInvoke LogonUser Win32 API.z.B.

http://www.pinvoke.net/default.aspx/advapi32/LogonUser.html

MSDN-Referenz hier...

http://msdn.microsoft.com/en-us/library/aa378184.aspx

Definitiv den Anmeldetyp verwenden wollen

LOGON32_LOGON_NETWORK (3)

Dadurch wird nur ein leichtes Token erstellt - perfekt für AuthN-Prüfungen. (andere Typen können zum Aufbau interaktiver Sitzungen usw. verwendet werden)

21voto

Mathieu Garstecki Punkte 1589

Eine vollständige .Net-Lösung ist die Verwendung der Klassen aus dem System.DirectoryServices-Namensraum. Sie ermöglichen die direkte Abfrage eines AD-Servers. Hier ist ein kleines Beispiel, das dies tun würde:

using (DirectoryEntry entry = new DirectoryEntry())
{
    entry.Username = "here goes the username you want to validate";
    entry.Password = "here goes the password";

    DirectorySearcher searcher = new DirectorySearcher(entry);

    searcher.Filter = "(objectclass=user)";

    try
    {
        searcher.FindOne();
    }
    catch (COMException ex)
    {
        if (ex.ErrorCode == -2147023570)
        {
            // Login or password is incorrect
        }
    }
}

// FindOne() didn't throw, the credentials are correct

Dieser Code stellt eine direkte Verbindung zum AD-Server her, wobei die angegebenen Anmeldeinformationen verwendet werden. Wenn die Anmeldeinformationen ungültig sind, löst searcher.FindOne() eine Ausnahme aus. Der ErrorCode ist derjenige, der dem COM-Fehler "ungültiger Benutzername/Passwort" entspricht.

Sie müssen den Code nicht als AD-Benutzer ausführen. Ich habe ihn sogar erfolgreich zur Abfrage von Informationen auf einem AD-Server von einem Client außerhalb der Domäne aus verwendet!

14voto

palswim Punkte 11356

Ein weiterer .NET-Aufruf zur schnellen Authentifizierung von LDAP-Anmeldeinformationen:

using System.DirectoryServices;

using(var DE = new DirectoryEntry(path, username, password)
{
    try
    {
        DE.RefreshCache(); // This will force credentials validation
    }
    catch (COMException ex)
    {
        // Validation failed - handle how you want
    }
}

11voto

Charles Bretana Punkte 137391

Versuchen Sie diesen Code (HINWEIS: Es wurde berichtet, dass es unter Windows Server 2000 nicht funktioniert)

#region NTLogonUser
#region Direct OS LogonUser Code
[DllImport( "advapi32.dll")]
private static extern bool LogonUser(String lpszUsername, 
    String lpszDomain, String lpszPassword, int dwLogonType, 
    int dwLogonProvider, out int phToken);

[DllImport("Kernel32.dll")]
private static extern int GetLastError();

public static bool LogOnXP(String sDomain, String sUser, String sPassword)
{
   int token1, ret;
   int attmpts = 0;

   bool LoggedOn = false;

   while (!LoggedOn && attmpts < 2)
   {
      LoggedOn= LogonUser(sUser, sDomain, sPassword, 3, 0, out token1);
      if (LoggedOn) return (true);
      else
      {
         switch (ret = GetLastError())
         {
            case (126): ; 
               if (attmpts++ > 2)
                  throw new LogonException(
                      "Specified module could not be found. error code: " + 
                      ret.ToString());
               break;

            case (1314): 
               throw new LogonException(
                  "Specified module could not be found. error code: " + 
                      ret.ToString());

            case (1326): 
               // edited out based on comment
               //  throw new LogonException(
               //   "Unknown user name or bad password.");
            return false;

            default: 
               throw new LogonException(
                  "Unexpected Logon Failure. Contact Administrator");
              }
          }
       }
   return(false);
}
#endregion Direct Logon Code
#endregion NTLogonUser

außer dass Sie Ihre eigene benutzerdefinierte Ausnahme für "LogonException" erstellen müssen

8voto

Michael Liu Punkte 48128

Die Windows-Authentifizierung kann aus verschiedenen Gründen fehlschlagen: ein falscher Benutzername oder ein falsches Kennwort, ein gesperrtes Konto, ein abgelaufenes Kennwort und vieles mehr. Um zwischen diesen Fehlern zu unterscheiden, rufen Sie den LogonUser API-Funktion über P/Invoke und prüfen Sie den Fehlercode, wenn die Funktion zurückgibt false :

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

using Microsoft.Win32.SafeHandles;

public static class Win32Authentication
{
    private class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private SafeTokenHandle() // called by P/Invoke
            : base(true)
        {
        }

        protected override bool ReleaseHandle()
        {
            return CloseHandle(this.handle);
        }
    }

    private enum LogonType : uint
    {
        Network = 3, // LOGON32_LOGON_NETWORK
    }

    private enum LogonProvider : uint
    {
        WinNT50 = 3, // LOGON32_PROVIDER_WINNT50
    }

    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool CloseHandle(IntPtr handle);

    [DllImport("advapi32.dll", SetLastError = true)]
    private static extern bool LogonUser(
        string userName, string domain, string password,
        LogonType logonType, LogonProvider logonProvider,
        out SafeTokenHandle token);

    public static void AuthenticateUser(string userName, string password)
    {
        string domain = null;
        string[] parts = userName.Split('\\');
        if (parts.Length == 2)
        {
            domain = parts[0];
            userName = parts[1];
        }

        SafeTokenHandle token;
        if (LogonUser(userName, domain, password, LogonType.Network, LogonProvider.WinNT50, out token))
            token.Dispose();
        else
            throw new Win32Exception(); // calls Marshal.GetLastWin32Error()
    }
}

Beispielhafte Verwendung:

try
{
    Win32Authentication.AuthenticateUser("EXAMPLE\\user", "P@ssw0rd");
    // Or: Win32Authentication.AuthenticateUser("user@example.com", "P@ssw0rd");
}
catch (Win32Exception ex)
{
    switch (ex.NativeErrorCode)
    {
        case 1326: // ERROR_LOGON_FAILURE (incorrect user name or password)
            // ...
        case 1327: // ERROR_ACCOUNT_RESTRICTION
            // ...
        case 1330: // ERROR_PASSWORD_EXPIRED
            // ...
        case 1331: // ERROR_ACCOUNT_DISABLED
            // ...
        case 1907: // ERROR_PASSWORD_MUST_CHANGE
            // ...
        case 1909: // ERROR_ACCOUNT_LOCKED_OUT
            // ...
        default: // Other
            break;
    }
}

Hinweis: LogonUser erfordert eine Vertrauensbeziehung mit der Domäne, für die Sie die Gültigkeit überprüfen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X