34 votes

Annuaire actif - Vérifier le nom d'utilisateur / mot de passe

Je suis en utilisant le code suivant sur Windows Vista Ultimate SP1 pour interroger notre serveur active directory pour vérifier le nom d'utilisateur et le mot de passe d'un utilisateur sur un domaine.

public Object IsAuthenticated()
{
    String domainAndUsername = strDomain + "\\" + strUser;
    DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, strPass);
    SearchResult result;
    try
    {
        //Bind to the native AdsObject to force authentication.         

        DirectorySearcher search = new DirectorySearcher(entry) { Filter = ("(SAMAccountName=" + strUser + ")") };

        search.PropertiesToLoad.Add("givenName"); // First Name                
        search.PropertiesToLoad.Add("sn"); // Last Name
        search.PropertiesToLoad.Add("cn"); // Last Name

        result = search.FindOne();

        if (null == result)
        {
            return null;
        }

        //Update the new path to the user in the directory.
        _path = result.Path;
        _filterAttribute = (String)result.Properties["cn"][0];
    }
    catch (Exception ex)
    {
        return new Exception("Error authenticating user. " + ex.Message);
    }
    return user;
}

l'objectif est de l'utiliser .NET 3.5, et compilé avec VS 2008 standard

Je suis connecté sous un compte de domaine qui est un administrateur de domaine où la demande est en cours d'exécution.

Le code fonctionne parfaitement sur windows XP, mais j'obtiens l'exception suivante lors de l'exécution sur Vista:

System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
   at System.DirectoryServices.DirectorySearcher.FindOne()
   at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()
   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
   at System.DirectoryServices.DirectorySearcher.FindOne()
   at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()

J'ai essayé de changer les types d'authentification, je ne suis pas sûr de ce qu'il se passe.


Voir aussi: http://stackoverflow.com/questions/290548/c-validate-a-username-and-password-against-active-directory

49voto

Steve Evans Points 668

Si vous êtes en utilisant .net 3.5 utiliser ce code à la place.

Pour authentifier un utilisateur:

PrincipalContext adContext = new PrincipalContext(ContextType.Domain);

using (adContext)
{
     return adContext.ValidateCredentials(UserName, Password);
}

Si vous avez besoin de trouver à l'utilisateur de R/W attributs de l'objet ce faire:

PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal foundUser = 
    UserPrincipal.FindByIdentity(context, "jdoe");

C'est en utilisant le Système.DirectoryServices.AccountManagement espace de noms, de sorte que vous aurez besoin de l'ajouter à votre utilisation de déclarations.

Si vous avez besoin de convertir un UserPrincipal objet à un objet DirectoryEntry de travailler avec le code existant, vous pouvez le faire:

DirectoryEntry userDE = (DirectoryEntry)foundUser.GetUnderlyingObject();

8voto

Pretzel Points 2277

J'ai trouvé que même code flottant autour de l'Internet sur plusieurs sites et il ne fonctionne pas pour moi. Steve Evans est probablement vrai que si vous êtes sur .NET 3.5, vous ne devriez pas utiliser ce code. Mais si vous ÊTES encore sur .NET 2.0, vous pouvez essayer ce pour s'Authentifier auprès de votre ANNONCE de services:

DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, 
   userName, password, 
   AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer);
object nativeObject = entry.NativeObject;

La première ligne crée un objet DirectoryEntry à l'aide de domaine, nom d'utilisateur et mot de passe. Il définit également le AuthenticationTypes. Remarquez comment je suis à la fois Sécurisé (Kerberos), l'Authentification et la connexion SSL en utilisant le "OU Logique" ( '|' ) de l'opérateur entre les deux paramètres.

La deuxième ligne de force la NativeObject de "l'entrée" de se Lier à l'ANNONCE services à l'aide de l'information de la première ligne.

Si une exception est levée, puis les informations d'identification (ou paramètres) ont été mauvais. Si aucune exception, vous êtes authentifié. Le message de l'exception habituellement indiquer ce qui s'est passé.

Ce code est assez similaire à ce que vous avez déjà, mais le domaine est utilisé lorsque vous avez "chemin", et le nom d'utilisateur n'est pas combiné avec le domaine. Assurez-vous de définir votre AuthenticationTypes correctement, trop. Cela peut faire ou défaire la possibilité de s'authentifier.

1voto

Michael G Points 2884

Je l'ai compris de toute façon Si vous passez dans le domaine avec le nom d'utilisateur sur Vista, il ne fonctionne pas comme "domaine utilisateur" donc juste passer "utilisateur" semble plutôt fonctionner bien - sauf que vous devez être sur le même domaine

0voto

Steven Robbins Points 18791

La liaison avec le LDAP nécessite-t-elle des privilèges élevés (UAC)? Vous pouvez essayer d'exécuter Visual Studio et / ou l'application en tant qu'administrateur et voir si cela aide. Si c'est le problème, vous pouvez toujours ajouter un manifeste à l'application et le définir pour exiger l'élévation, de cette façon il invite quand un utilisateur l'exécute.

Je ne sais pas pourquoi il faudrait des privilèges élevés, mais il vaut la peine d'essayer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X