579 votes

Valider un nom d'utilisateur et un mot de passe par rapport à Active Directory ?

Comment puis-je valider un nom d'utilisateur et un mot de passe par rapport à Active Directory ? Je veux simplement vérifier si un nom d'utilisateur et un mot de passe sont corrects.

691voto

marc_s Points 321990

Si vous travaillez avec .NET 3.5 ou une version plus récente, vous pouvez utiliser la fonction System.DirectoryServices.AccountManagement et vérifier facilement vos informations d'identification :

// create a "principal context" - e.g. your domain (could be machine, too)
using(PrincipalContext pc = new PrincipalContext(ContextType.Domain, "YOURDOMAIN"))
{
    // validate the credentials
    bool isValid = pc.ValidateCredentials("myuser", "mypassword");
}

C'est simple, c'est fiable, c'est du code géré à 100 % en C# de votre côté - que demander de plus ? :-)

Lisez tout à ce sujet ici :

1 votes

J'ai essayé : PrincipalContext pc = new PrincipalContext(ContextType.Domain, "yourdomain") ; Votre kilométrage peut varier.

0 votes

Christian : vous avez tout à fait raison. Je n'avais pas de serveur sous la main pour tester mes hypothèses - et elles étaient fausses. Vous avez besoin du nom de domaine en clair, et non du descripteur de domaine LDAP. Merci de me l'avoir fait remarquer !

1 votes

Cela a très bien fonctionné, sauf que pour moi, j'ai dû préfixer le nom d'utilisateur avec le nom de domaine, c'est-à-dire que pc.ValidateCredentials("DOMAN"). \\UserName ", " Mot de passe ") ;

74voto

Dining Philanderer Points 1519

Nous le faisons sur notre Intranet

Vous devez utiliser System.DirectoryServices ;

Voici l'essentiel du code

DirectoryEntry adsEntry = new DirectoryEntry(path, strAccountId, strPassword);
DirectorySearcher adsSearcher = new DirectorySearcher(adsEntry);
//adsSearcher.Filter = "(&(objectClass=user)(objectCategory=person))";
adsSearcher.Filter = "(sAMAccountName=" + strAccountId + ")";

try 
{
    SearchResult adsSearchResult = adsSearcher.FindOne();
    bSucceeded = true;

    strAuthenticatedBy = "Active Directory";
    strError = "User has been authenticated by Active Directory.";
    adsEntry.Close();
}
catch (Exception ex)
{
    // Failed to authenticate. Most likely it is caused by unknown user
    // id or bad strPassword.
    strError = ex.Message;
    adsEntry.Close();
}

12 votes

Que mettez-vous dans "path" ? Le nom du domaine ? Le nom du serveur ? Le chemin LDAP vers le domaine ? Le chemin LDAP vers le serveur ?

4 votes

Réponse1 : Non, nous l'exécutons en tant que service Web afin qu'il puisse être appelé à partir de plusieurs endroits dans l'application Web principale. Réponse 2 : Le chemin contient des informations LDAP... LDAP://DC=domainname1,DC=domainname2,DC=com

4 votes

Il semblerait que cela puisse permettre une injection LDAP. Vous pouvez vous assurer d'échapper ou de supprimer toute parenthèse dans le champ strAccountId

37voto

Steven A. Lowe Points 40596

solution très simple utilisant les DirectoryServices :

using System.DirectoryServices;

//srvr = ldap server, e.g. LDAP://domain.com
//usr = user name
//pwd = user password
public bool IsAuthenticated(string srvr, string usr, string pwd)
{
    bool authenticated = false;

    try
    {
        DirectoryEntry entry = new DirectoryEntry(srvr, usr, pwd);
        object nativeObject = entry.NativeObject;
        authenticated = true;
    }
    catch (DirectoryServicesCOMException cex)
    {
        //not authenticated; reason why is in cex
    }
    catch (Exception ex)
    {
        //not authenticated due to some other exception [this is optional]
    }

    return authenticated;
}

l'accès à NativeObject est nécessaire pour détecter un mauvais utilisateur/mot de passe.

4 votes

Ce code est mauvais car il effectue également un contrôle d'autorisation (vérifier si l'utilisateur est autorisé à lire les informations d'Active Directory). Le nom d'utilisateur et le mot de passe peuvent être valides, mais l'utilisateur n'est pas autorisé à lire les informations - et obtenir une exception. En d'autres termes, vous pouvez avoir un nom d'utilisateur et un mot de passe valides, mais obtenir quand même une exception.

2 votes

Je suis actuellement en train de demander l'autorisation de la indigène équivalent de PrincipleContext - qui n'existe que dans .NET 3.5. Mais si vous utilisez .NET 3.5 ou une version plus récente, vous devez utiliser la méthode suivante PrincipleContext

28voto

Alan Points 21367

Malheureusement, il n'existe pas de moyen "simple" de vérifier les informations d'identification d'un utilisateur dans AD.

Avec toutes les méthodes présentées jusqu'ici, vous pouvez obtenir un faux négatif : Les références d'un utilisateur seront valides, mais AD renverra un faux négatif dans certaines circonstances :

  • L'utilisateur doit changer son mot de passe à la prochaine connexion.
  • Le mot de passe de l'utilisateur a expiré.

ActiveDirectory ne vous permettra pas d'utiliser LDAP pour déterminer si un mot de passe est invalide du fait qu'un utilisateur doit changer de mot de passe ou que son mot de passe a expiré.

Pour déterminer si le mot de passe a été modifié ou s'il a expiré, vous pouvez appeler Win32:LogonUser(), et vérifier le code d'erreur Windows pour les 2 constantes suivantes :

  • ERROR_PASSWORD_MUST_CHANGE = 1907
  • ERROR_PASSWORD_EXPIRED = 1330

1 votes

Puis-je vous demander où vous avez trouvé les devinitions pour Expired et Must_Change... Je ne les ai trouvées nulle part ailleurs qu'ici :)

1 votes

0 votes

Merci. J'essayais de comprendre comment ma validation renvoyait tout le temps false. C'était parce que l'utilisateur devait changer son mot de passe.

22voto

stephbu Points 4440

La méthode la plus simple consiste probablement à invoquer l'API Win32 de LogonUser, par exemple.

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

Référence MSDN ici...

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

Il faut absolument utiliser le type de connexion

LOGON32_LOGON_NETWORK (3)

Cela crée un jeton léger uniquement - parfait pour les contrôles AuthN. (d'autres types peuvent être utilisés pour construire des sessions interactives, etc.)

0 votes

Comme le souligne @Alan, l'API LogonUser présente de nombreuses caractéristiques utiles au-delà d'un appel à System.DirectoryServices.

4 votes

@cciotti : Non, c'est faux. La MEILLEURE façon d'authentifier correctement quelqu'un est d'utiliser LogonUserAPI comme @stephbu l'a écrit. Toutes les autres méthodes décrites dans ce post ne fonctionneront PAS à 100%. Juste une note cependant, je crois que vous devez être joint au domaine afin d'appeler LogonUser.

0 votes

@Alan pour générer des informations d'identification, vous devez être en mesure de vous connecter au domaine en fournissant un compte de domaine valide. Cependant, je suis presque sûr que votre machine ne doit pas nécessairement être membre du domaine.

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