Je veux valider un ensemble de justificatifs auprès du contrôleur de domaine. p. ex.:
Nom d'utilisateur : STACKOVERFLOW\joel
Mot de passe : splotchy
Méthode 1. Interroger Active Directory avec Impersonation
Beaucoup de gens suggèrent d'interroger l'Active Directory pour quelque chose. Si une exception est levée, alors vous savez que les justificatifs ne sont pas valides - comme suggéré dans cette question stackoverflow.
Il y a cependant quelques sérieux inconvénients à cette approche:
-
Vous n'authentifiez pas seulement un compte de domaine, mais vous faites aussi une vérification d'autorisation implicite. C'est-à-dire, vous lisez des propriétés de l'AD en utilisant un jeton d'impersonation. Que se passe-t-il si le compte par ailleurs valide n'a pas le droit de lecture de l'AD ? Par défaut, tous les utilisateurs ont un accès en lecture, mais des politiques de domaine peuvent être définies pour désactiver les autorisations d'accès pour les comptes (et/ou groupes) restreints.
-
Le binding contre l'AD a un sérieux surcoût, le cache du schéma AD doit être chargé au client (cache ADSI dans le fournisseur ADSI utilisé par DirectoryServices). Cela consomme à la fois des ressources réseau et du serveur AD - et est trop coûteux pour une opération simple comme l'authentification d'un compte utilisateur.
-
Vous vous appuyez sur un échec d'exception pour un cas non exceptionnel, et en supposant que cela signifie un nom d'utilisateur et un mot de passe invalides. D'autres problèmes (p. ex. échec du réseau, échec de la connectivité AD, erreur d'allocation de mémoire, etc) sont alors mal interprétés comme un échec d'authentification.
Méthode 2. API Win32 LogonUser
D'autres ont suggéré d'utiliser la fonction API LogonUser()
. Cela semble bien, mais malheureusement l'utilisateur appelant a parfois besoin d'une permission généralement donnée uniquement au système d'exploitation lui-même :
Le processus appelant LogonUser nécessite le privilège SE_TCB_NAME. Si le processus appelant n'a pas ce privilège, LogonUser échoue et GetLastError renvoie ERROR_PRIVILEGE_NOT_HELD.
Dans certains cas, le processus qui appelle LogonUser doit également avoir le privilège SE_CHANGE_NOTIFY_NAME activé ; sinon, LogonUser échoue et GetLastError renvoie ERROR_ACCESS_DENIED. Ce privilège n'est pas requis pour le compte système local ou les comptes qui sont membres du groupe des administrateurs. Par défaut, SE_CHANGE_NOTIFY_NAME est activé pour tous les utilisateurs, mais certains administrateurs peuvent le désactiver pour tout le monde.
Accorder le privilège "Agir comme une partie du système d'exploitation" n'est pas quelque chose que vous voulez faire à la légère - comme le souligne Microsoft dans un article de la base de connaissances :
...le processus qui appelle LogonUser doit avoir le privilège SE_TCB_NAME (dans Gestionnaire d'utilisateurs, c'est le droit "Agir comme partie du système d'exploitation"). Le privilège SE_TCB_NAME est très puissant et ne doit pas être accordé à n'importe quel utilisateur arbitraire juste pour qu'il puisse exécuter une application qui a besoin de valider des justificatifs.
De plus, un appel à LogonUser()
échouera si un mot de passe vide est spécifié.
Quelle est la bonne façon d'authentifier un ensemble de justificatifs de domaine ?
Je happen à appeler à partir de code managé, mais il s'agit d'une question Windows générale. On peut supposer que les clients ont le .NET Framework 2.0 installé.