Comment faire pour authentifier sur Active Directory à l’aide de l’authentification par formulaires et Visual C# .NET

Cet article fait référence aux espaces de noms bibliothèque de classes Microsoft.NET Framework suivant :
  • System.Text
  • System.DirectoryServices
  • System.Security.Principal
  • System.Web.Security

Résumé

Cet article explique, étape par étape, comment une application ASP.NET peut utiliser l'authentification par formulaires pour permettre aux utilisateurs de s'authentifier sur Active Directory à l'aide du LDAP Lightweight Directory Access Protocol (). Une fois que 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.

Créer une application Web d’ASP.NET dans Visual C# .NET

Suivez ces étapes pour créer une nouvelle application ASP.NET Web nommée FormsAuthAd dans Visual C# .NET :
  1. Démarrez Microsoft Visual Studio .NET.
  2. Dans le menu Fichier, pointez sur Nouveau, puis cliquez sur Projet.
  3. Cliquez sur Projets Visual C# sous Types de projets, puis cliquez sur ASP.NET Web Application sous modèles.
  4. Dans la zone emplacement , remplacez WebApplication1 FormsAuthAd.
  5. Cliquez sur OK.
  6. Cliquez sur le nœud références dans l’Explorateur de solutions, puis cliquez sur Ajouter une référence.
  7. Sous l’onglet .NET de la boîte de dialogue Ajouter une référence , cliquez sur System.DirectoryServices.dll, cliquez sur Sélectionner, puis cliquez sur OK.

Écrire le code d’authentification

Suivez ces étapes pour créer un nouveau fichier de classe nommé LdapAuthentication.cs :
  1. Dans l’Explorateur de solutions, cliquez sur le nœud de projet, pointez sur Ajouter, puis cliquez sur Ajouter un nouvel élément.
  2. Sous modèles, cliquez sur une classe .
  3. Tapez LdapAuthentication.cs dans la zone nom , puis cliquez sur Ouvrir.
  4. Remplacez le code existant dans le fichier LdapAuthentication.cs par le code suivant.
    using System;using System.Text;
    using System.Collections;
    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();
    }
    }
    }

Le code d’authentification accepte un domaine, un nom d’utilisateur, un mot de passe et un chemin d’accès à l’arborescence dans Active Directory. Ce code utilise le fournisseur d’annuaire LDAP.

Le code dans la page Logon.aspx appelle la méthode LdapAuthentication.IsAuthenticated et passe les informations d’identification collectées auprès de l’utilisateur. Ensuite, un objet DirectoryEntry est créé avec le chemin d’accès à l’arborescence du répertoire, le nom d’utilisateur et le mot de passe. Le nom d’utilisateur doit être dans le format « DOMAINE\nom_utilisateur ». L’objet DirectoryEntry essaie de forcer la liaison de l’objet AdsObject en obtenant la propriété NativeObject ne . Si cela réussit, l’attribut CN de l’utilisateur est obtenue en créant un objet DirectorySearcher et en filtrant le SAMAccountName. Une fois que l’utilisateur est authentifié, la méthode IsAuthenticated renvoie la valeur true.

Pour obtenir une liste des 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 appartient l’utilisateur en créant un objet DirectorySearcher et par le filtrage en fonction de l’attribut memberOf . Cette méthode retourne une liste de groupes séparée par des canaux (|).

Notez que la méthode LdapAuthentication.GetGroups manipule et tronque les chaînes. Cela permet de réduire la longueur de la chaîne qui est stockée dans le cookie d’authentification. Si la chaîne n’est pas tronquée, le format de chaque groupe apparaît comme suit.
CN=...,...,DC=domain,DC=com
Cela peut créer une très longue chaîne. Si la longueur de cette chaîne est supérieure à la longueur du cookie, les navigateurs ne peuvent pas accepter le cookie d’authentification, et vous allez être redirigé vers la page d’ouverture de session. Toutefois, si vous êtes dans un environnement à plusieurs domaines, vous devrez conserver le nom de domaine avec le nom du groupe, car les groupes dans des domaines différents peuvent avoir le même nom de groupe. Vous devez conserver le nom de domaine pour différencier un groupe d’un autre.

La plupart des navigateurs prennent en charge les cookies de 4 096 octets. Si cette chaîne peut potentiellement dépasse la longueur du cookie, vous souhaiterez peut-être stocker les informations de groupe dans l’objet Cache d’ASP.NET ou dans une base de données. Vous pouvez également chiffrer les informations de groupe et de stocker ces informations dans un champ de formulaire masqué.

Écrire le code Global.asax

Le code dans le fichier Global.asax fournit un gestionnaire d’événements Application_AuthenticateRequest . Ce gestionnaire d’événements récupère le cookie d’authentification à partir de la collection Context.Request.Cookies , décrypte le cookie et récupère la liste des groupes qui seront stockées dans la propriété FormsAuthenticationTicket.UserData . Les groupes apparaissent dans une liste séparée par des canaux qui est créée dans la page Logon.aspx.

Le code analyse la chaîne en un tableau de chaînes pour créer un objet GenericPrincipal . Une fois l’objet GenericPrincipal créé, cet objet est placé dans la propriété HttpContext.User .
  1. Dans l’Explorateur de solutions, cliquez avec droit de Global.asaxet puis cliquez sur Afficher le Code.
  2. Ajoutez le code suivant en haut du fichier code-behind Global.asax.cs :
    using System.Web.Security;using System.Security.Principal;

  3. Remplacez le Gestionnaire d’événements vide existant 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;

    }

Modifier le fichier Web.config

Dans cette section, vous configurez le < forms >et l' < authentification >les éléments < autorisation > dans le fichier Web.config. Avec ces modifications, 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 autoriser uniquement certains utilisateurs et aux groupes l’accès à l’application.

Remplacez le code existant dans le fichier Web.config par le code suivant.
<?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 < identity impersonate = « true » / > . Cela permet à ASP.NET d'emprunter l'identité du compte configuré comme compte anonyme à partir de Microsoft Internet Information Services (IIS). Avec cette configuration, toutes les demandes à cette application de s’exécuter dans le contexte de sécurité du compte configuré. L’utilisateur fournit des informations d’identification pour l’authentification sur Active Directory, mais le compte qui accède à Active Directory est le compte configuré. Pour plus d’informations, consultez la section références .

Configurer IIS pour l’authentification anonyme

Pour configurer IIS pour l’authentification anonyme, procédez comme suit :
  1. Dans IIS, développez le nœud de l’ordinateur de votre serveur, développez Sites Web, développez Site Web par défaut, droit sur FormsAuthAd, puis cliquez sur Propriétés.
  2. Cliquez sur l' Onglet sécurité de répertoire, puis cliquez sur Modifier sous connexions anonymes et contrôle d’authentification.
  3. Vérifiez le compte anonyme pour l’application à un compte qui possède des autorisations dans Active Directory.
  4. Désactivez la case à cocher Autoriser IIS à mot de passe.
  5. Dans la section « Accès authentifié », désactivez la case à cocher « Authentification intégrée de Windows ».
  6. Cliquez sur OK.
  7. Cliquez sur Appliquer
Le compte par défaut IUSR_nom_ordinateur ne dispose pas d’autorisation d’Active Directory.

Créer la page Logon.aspx

Suivez ces étapes pour créer un formulaire Web ASP.NET nommée Logon.aspx :
  1. Dans l’Explorateur de solutions, cliquez sur le nœud du projet, pointez sur Ajouter, puis cliquez sur Ajouter un formulaire Web.
  2. Tapez Logon.aspx dans la zone nom , puis cliquez sur Ouvrir.
  3. Dans l’Explorateur de solutions, droit sur Logon.aspx, puis cliquez sur Concepteur de vues.
  4. Cliquez sur l’onglet HTML dans le concepteur.
  5. Remplacez le code existant par le code suivant.
    <%@ Page language="c#" AutoEventWireup="true" %><%@ Import Namespace="FormsAuth" %>
    <html>
    <body>
    <form id="Login" method="post" runat="server">
    <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://corp.com"; //Fully-qualified Domain Name
    LdapAuthentication adAuth = new LdapAuthentication(adPath);
    try
    {
    if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
    {
    String groups = adAuth.GetGroups();

    //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>
  6. Modifier le chemin d’accès dans la page Logon.aspx pour pointer vers votre serveur d’annuaire LDAP.
La page Logon.aspx est une page qui recueille les informations de l’utilisateur et appellent des méthodes sur la classe LdapAuthentication . Une fois que le code authentifie l’utilisateur et pour obtenir une liste des groupes, le code crée un objet FormsAuthenticationTicket , crypte le ticket, ajoute le ticket crypté dans un cookie, ajoute le cookie à la collection HttpResponse.Cookies et puis redirige la demande vers l’URL demandée initialement.

Modifier la page WebForm1.aspx

La page WebForm1.aspx est la page qui est demandée à l’origine. Lorsque l’utilisateur demande cette page, la demande est redirigée vers la page Logon.aspx. Une fois que la requête est authentifiée, la demande est redirigée vers la page WebForm1.aspx.
  1. Dans l’Explorateur de solutions, cliquez sur WebForm1.aspx, puis cliquez sur Concepteur de vues.
  2. Cliquez sur l’onglet HTML dans le concepteur.
  3. Remplacez le code existant par le code suivant.
    <%@ Page language="c#" AutoEventWireup="true" %><%@ Import Namespace="System.Security.Principal" %>
    <html>
    <body>
    <form id="Form1" method="post" runat="server">
    <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>

  4. Enregistrez tous les fichiers, puis compilez le projet.
  5. Demandez la page WebForm1.aspx. Notez que vous êtes redirigé vers Logon.aspx.
  6. Tapez les informations d’identification d’ouverture de session, 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 de la propriété Context.User.AuthenticationType .
Remarque Microsoft recommande d’utiliser le cryptage Secure Sockets Layer (SSL) lorsque vous utilisez l’authentification par formulaire. C’est parce que l’utilisateur étant identifié d’après le cookie d’authentification et le cryptage SSL sur cette application empêche quiconque de compromettre le cookie d’authentification et toute autre information sensible transmise.

Références

Pour plus d’informations, cliquez sur les numéros ci-dessous pour afficher les articles correspondants dans la Base de connaissances Microsoft :

Présentation de la sécurité ASP.NET 306590

317012 identité du processus et de la demande dans ASP.NET

311495 comment implémenter la sécurité basée sur les rôles avec l’authentification basée sur les formulaires dans votre application ASP.NET à l’aide de Visual C# .NET

313091 comment créer des clés à l’aide de Visual Basic .NET pour utiliser l’authentification par formulaire

313116 les demandes d’authentification de formulaires ne sont pas dirigés vers la page loginUrl

Propriétés

ID d'article : 316748 - Dernière mise à jour : 9 janv. 2017 - Révision : 1

Commentaires