Authentification des services de domaine Active Directory à partir d'ASP .NET
Cette rubrique montre comment une application ASP.NET peut utiliser l'authentification par formulaire pour permettre aux utilisateurs de s'authentifier auprès des services de domaine Active Directory en utilisant le protocole LDAP (Lightweight Directory Access Protocol). Lorsque l'utilisateur est authentifié et redirigé, vous pouvez utiliser la méthode Application_AuthenticateRequest du fichier Global.asax pour stocker un objet GenericPrincipal dans la propriété HttpContext.User qui circule dans la demande.
Pour créer une application Web ASP.NET
Démarrez Microsoft Visual Studio .NET.
Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Fichier.
Cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur Application Web ASP.NET sous Modèles.
Dans la zone Nom, tapez FormsAuthAd.
Si vous utilisez le serveur local, laissez l'adresse par défaut https://localhost dans la zone Serveur. Sinon, ajoutez le chemin d'accès vers votre serveur. Cliquez sur OK.
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le nœud Références et cliquez sur Ajouter une référence.
Sous l'onglet .NET dans la boîte de dialogue Ajouter une référence, cliquez sur System.DirectoryServices.dll, puis sur Sélectionner, et sur OK.
Pour ajouter un code d'authentification System.DirectoryServices
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, pointez sur Ajouter, puis cliquez sur Ajouter un nouvel élément.
Sous Modèles, cliquez sur Classe.
Tapez LdapAuthentication.cs dans la zone Nom, puis cliquez sur Ouvrir.
Remplacez le code existant dans le fichier LdapAuthentication.cs par le code suivant :
using System; using System.Text; using System.Collections; using System.Web.Security; using System.Security.Principal; using System.DirectoryServices; namespace FormsAuth { public class LdapAuthentication { private string _path; private string _filterAttribute; public LdapAuthentication(string path) { _path = path; } public bool IsAuthenticated(string domain, string username, string pwd) { string domainAndUsername = domain + @"\" + username; DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd); try { //Bind to the native AdsObject to force authentication. object obj = entry.NativeObject; DirectorySearcher search = new DirectorySearcher(entry); search.Filter = "(SAMAccountName=" + username + ")"; search.PropertiesToLoad.Add("cn"); SearchResult result = search.FindOne(); if(null == result) { return false; } //Update the new path to the user in the directory. _path = result.Path; _filterAttribute = (string)result.Properties["cn"][0]; } catch (Exception ex) { throw new Exception("Error authenticating user. " + ex.Message); } return true; } public string GetGroups() { DirectorySearcher search = new DirectorySearcher(_path); search.Filter = "(cn=" + _filterAttribute + ")"; search.PropertiesToLoad.Add("memberOf"); StringBuilder groupNames = new StringBuilder(); try { SearchResult result = search.FindOne(); int propertyCount = result.Properties["memberOf"].Count; string dn; int equalsIndex, commaIndex; for(int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++) { dn = (string)result.Properties["memberOf"][propertyCounter]; equalsIndex = dn.IndexOf("=", 1); commaIndex = dn.IndexOf(",", 1); if(-1 == equalsIndex) { return null; } groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1)); groupNames.Append("|"); } } catch(Exception ex) { throw new Exception("Error obtaining group names. " + ex.Message); } return groupNames.ToString(); } } }
Dans la procédure précédente, le code d'authentification accepte un domaine, un nom d'utilisateur, un mot de passe et un chemin d'accès vers l'arborescence dans les services de domaine Active Directory. Ce code utilise le fournisseur d'annuaires LDAP. Le code de la page Logon.aspx appelle la méthode LdapAuthentication.IsAuthenticated et passe les informations d'identification collectées à partir de l'utilisateur. Un objet DirectoryEntry est ensuite créé avec le chemin d'accès vers l'arborescence d'annuaires, le nom d'utilisateur et le mot de passe. Le nom d'utilisateur doit être au format domaine\NomUtilisateur.
L'objet DirectoryEntry tente ensuite de forcer la liaison de l'objet AdsObject en obtenant la propriété NativeObject. En cas de réussite, l'attribut CN pour l'utilisateur est obtenu en créant un objet DirectorySearcher et en positionnant un filtre sur sAMAccountName. Pour plus d'informations sur sAMAccountName dans le schéma des services de domaine Active Directory, voir les rubriques sur « sAMAccountName » ou sur l'attribut « SAM-Account-Name » dans MSDN Library. Lorsque l'utilisateur est authentifié, la méthode IsAuthenticated retourne true. Pour obtenir une liste de groupes auxquels l'utilisateur appartient, ce code appelle la méthode LdapAuthentication.GetGroups. La méthode LdapAuthentication.GetGroups obtient une liste des groupes de sécurité et de distribution auxquels l'utilisateur appartient en créant un objet DirectorySearcher et en positionnant un filtre selon l'attribut memberOf. Pour plus d'informations sur memberOf dans le schéma des services de domaine Active Directory, voir les rubriques sur « memberOf » ou sur l'attribut « Is-Member-Of-DL » dans MSDN Library. Cette méthode retourne une liste de groupes séparés par des barres verticales (|). Notez que la méthode LdapAuthentication.GetGroups manipule et tronque des chaînes. Cela réduit la longueur de la chaîne stockée dans le cookie d'authentification. Si la chaîne n'est pas tronquée, le format de chaque groupe est comme suit :
CN=...,...,DC=domain,DC=com
La méthode LdapAuthentication.GetGroups peut retourner une très longue chaîne. Si la longueur de la chaîne est supérieure à celle du cookie, le cookie d'authentification risque de ne pas être créé. Si cette chaîne risque de dépasser la longueur du cookie, vous pouvez stocker les informations de groupe dans l'objet ASP.NET Cache ou dans une base de données. Vous pouvez également chiffrer les informations de groupe et les stocker dans un champ de formulaire masqué.
Le code du fichier Global.asax fournit un gestionnaire d'événements Application_AuthenticateRequest. Ce gestionnaire d'événements récupère le cookie d'authentification dans la collection Context.Request.Cookies, déchiffre le cookie et récupère la liste des groupes qui seront stockés dans la propriété FormsAuthenticationTicket.UserData. Les groupes sont affichés, séparés par des barres verticales, dans une liste créée dans la page Logon.aspx. Le code analyse la chaîne dans un tableau de chaînes pour créer un objet GenericPrincipal. Lorsque l'objet GenericPrincipal est créé, il est placé dans la propriété HttpContext.User.
Pour écrire le code Global.asax
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur Global.asax, puis cliquez sur Afficher le code.
Ajoutez le code suivant en haut du code-behind pour le fichier Global.asax.cs :
using System.Web.Security; using System.Security.Principal;
Remplacez le gestionnaire d'événements vide pour Application_AuthenticateRequest par le code suivant :
void Application_AuthenticateRequest(object sender, EventArgs e) { string cookieName = FormsAuthentication.FormsCookieName; HttpCookie authCookie = Context.Request.Cookies[cookieName]; if(null == authCookie) { //There is no authentication cookie. return; } FormsAuthenticationTicket authTicket = null; try { authTicket = FormsAuthentication.Decrypt(authCookie.Value); } catch(Exception ex) { //Write the exception to the Event Log. return; } if(null == authTicket) { //Cookie failed to decrypt. return; } //When the ticket was created, the UserData property was assigned a //pipe-delimited string of group names. string[] groups = authTicket.UserData.Split(new char[]{'|'}); //Create an Identity. GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication"); //This principal flows throughout the request. GenericPrincipal principal = new GenericPrincipal(id, groups); Context.User = principal; }
Dans cette rubrique, vous configurez les <formulaires>, l'<authentification> et les éléments d'<autorisation> dans le fichier Web.config. Avec ces changements, seuls les utilisateurs authentifiés peuvent accéder à l'application, et les demandes non authentifiées sont redirigées vers une page Logon.aspx. Vous pouvez modifier cette configuration pour permettre à certains utilisateurs et groupes uniquement d'accéder à l'application.
Pour modifier le fichier Web.config
Ouvrez Web.config dans le Bloc-notes.
Remplacez le code existant par celui-ci :
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="logon.aspx" name="adAuthCookie" timeout="10" path="/"> </forms> </authentication> <authorization> <deny users="?"/> <allow users="*"/> </authorization> <identity impersonate="true"/> </system.web> </configuration>
Notez l'élément de configuration suivant :
<identity impersonate="true"/>
Du fait de cet élément, ASP.NET emprunte à Microsoft Internet Information Services (IIS) le compte configuré comme le compte anonyme. Grâce à cette configuration, toutes les demandes à destination de cette application s'exécutent dans le contexte de sécurité du compte configuré. L'utilisateur fournit des informations d'identification pour s'authentifier auprès des services de domaine Active Directory, mais le compte qui accède aux services de domaine Active Directory est le compte configuré.
Pour configurer IIS pour l'authentification anonyme
Dans le Gestionnaire des services Internet (dans Outils d'administration) ou le composant logiciel enfichable MMC pour IIS, cliquez avec le bouton droit sur le site Web pour lequel vous souhaitez configurer l'authentification, puis cliquez sur Propriétés.
Cliquez sur l'onglet Sécurité du répertoire, puis sous Authentification et contrôle d'accès, cliquez sur Modifier.
Activez la case à cocher Authentification anonyme (libellée Activer la connexion anonyme dans Windows Server 2003).
Changez le compte anonyme pour l'application en un compte qui dispose des autorisations sur les services de domaine Active Directory.
Désactivez la case à cocher Autoriser la vérification de mot de passe par IIS, le cas échéant. Le compte IUSR*_<NomOrdinateur>* par défaut ne dispose pas des autorisations sur les services de domaine Active Directory.
Pour créer la page Logon.aspx
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur le nœud du projet, pointez sur Ajouter, puis cliquez sur Ajouter un formulaire Web.
Dans la zone Nom, tapez Logon.aspx, puis cliquez sur Ouvrir.
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur Logon.aspx, puis cliquez sur Concepteur de vues.
Cliquez sur l'onglet HTML dans le Concepteur.
Remplacez le code existant par celui-ci :
<%@ Page language="c#" AutoEventWireup="true" %> <%@ Import Namespace="FormsAuth" %> <html> <body> <form id="Login" method="post" > <asp:Label ID="Label1" Runat=server >Domain:</asp:Label> <asp:TextBox ID="txtDomain" Runat=server ></asp:TextBox><br> <asp:Label ID="Label2" Runat=server >Username:</asp:Label> <asp:TextBox ID=txtUsername Runat=server ></asp:TextBox><br> <asp:Label ID="Label3" Runat=server >Password:</asp:Label> <asp:TextBox ID="txtPassword" Runat=server TextMode=Password></asp:TextBox><br> <asp:Button ID="btnLogin" Runat=server Text="Login" OnClick="Login_Click"></asp:Button><br> <asp:Label ID="errorLabel" Runat=server ForeColor=#ff3300></asp:Label><br> <asp:CheckBox ID=chkPersist Runat=server Text="Persist Cookie" /> </form> </body> </html> <script runat=server> void Login_Click(object sender, EventArgs e) { string adPath = "LDAP://" + txtDomain.Text; LdapAuthentication adAuth = new LdapAuthentication(adPath); try { if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) { string groups = adAuth.GetGroups(txtDomain.Text, txtUsername.Text, txtPassword.Text); //Create the ticket, and add the groups. bool isCookiePersistent = chkPersist.Checked; FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups); //Encrypt the ticket. string encryptedTicket = FormsAuthentication.Encrypt(authTicket); //Create a cookie, and then add the encrypted ticket to the cookie as data. HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); if(true == isCookiePersistent) authCookie.Expires = authTicket.Expiration; //Add the cookie to the outgoing cookies collection. Response.Cookies.Add(authCookie); //You can redirect now. Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false)); } else { errorLabel.Text = "Authentication did not succeed. Check user name and password."; } } catch(Exception ex) { errorLabel.Text = "Error authenticating. " + ex.Message; } } </script>
Modifiez le chemin d'accès dans la page Logon.aspx pour désigner votre serveur d'annuaires LDAP.
La page Logon.aspx collecte les informations de l'utilisateur et appelle les méthodes sur la classe LdapAuthentication. Lorsque le code a authentifié l'utilisateur et obtenu une liste de groupes, il crée un objet FormsAuthenticationTicket, chiffre le ticket, ajoute le ticket chiffré à un cookie, ajoute le cookie à la collection HttpResponse.Cookies et redirige la demande vers l'URL demandée à l'origine.
La page WebForm1.aspx est celle demandée à l'origine. Lorsque l'utilisateur demande cette page, la demande est redirigée vers la page Logon.aspx. Lorsque la demande est authentifiée, elle est redirigée vers la page WebForm1.aspx.
Pour modifier la page WebForm1.aspx
Dans l'Explorateur de solutions, cliquez avec le bouton droit sur WebForm1.aspx, puis cliquez sur Concepteur de vues.
Cliquez sur l'onglet HTML dans le concepteur.
Remplacez le code existant par celui-ci :
<%@ Page language="c#" AutoEventWireup="true" %> <%@ Import Namespace="System.Security.Principal" %> <html> <body> <form id="Form1" method="post" > <asp:Label ID="lblName" Runat=server /><br> <asp:Label ID="lblAuthType" Runat=server /> </form> </body> </html> <script runat=server> void Page_Load(object sender, EventArgs e) { lblName.Text = "Hello " + Context.User.Identity.Name + "."; lblAuthType.Text = "You were authenticated using " + Context.User.Identity.AuthenticationType + "."; } </script>
Enregistrez tous les fichiers, puis compilez le projet.
Demandez la page WebForm1.aspx. Notez que vous êtes redirigé vers Logon.aspx.
Tapez les informations d'identification pour la connexion, puis cliquez sur Envoyer. Lorsque vous êtes redirigé vers WebForm1.aspx, notez que votre nom d'utilisateur s'affiche et que LdapAuthentication est le type d'authentification pour la propriété Context.User.AuthenticationType.
Remarque : |
---|
Il est recommandé d'utiliser le chiffrement Secure Sockets Layer (SSL) lorsque vous utilisez l'authentification par formulaire. Cette recommandation est due au fait que l'utilisateur est identifié d'après le cookie d'authentification et que le chiffrement SSL sur cette application empêche quiconque de compromettre le cookie d'authentification et toute autre information importante en cours de transmission. |
Voir aussi
Référence
System.DirectoryServices
DirectoryEntry
DirectorySearcher
Concepts
Rubriques de programmation avancée
Send comments about this topic to Microsoft.
Copyright © 2007 par Microsoft Corporation. Tous droits réservés.