Modalità di autenticazione in Active Directory utilizzando l'autenticazione basata su form e Visual C# .NET

In questo articolo fa riferimento a spazi dei nomi Microsoft.NET Framework Class Library seguenti:
  • System.Text
  • System.DirectoryServices
  • System.Security.Principal
  • System.Web.Security

Riepilogo

In questo articolo viene illustrata un'applicazione ASP.NET utilizzo autenticazione basata su form per consentire agli utenti di Active Directory per autenticare mediante l'utilizzo di LDAP Lightweight Directory Access Protocol (). Dopo che l'utente è autenticato e reindirizzato, è possibile utilizzare il metodo Application_AuthenticateRequest del file Global. asax per memorizzare un oggetto GenericPrincipal nella proprietà HttpContext. User che passa la richiesta.

Creare un'applicazione Web ASP.NET in Visual C# .NET

Attenersi alla procedura seguente per creare una nuova applicazione Web ASP.NET denominata FormsAuthAd in Visual C# .NET:
  1. Avviare Microsoft Visual Studio .NET.
  2. Dal menu File , scegliere Nuovo, quindi progetto.
  3. Fare clic su Progetti di Visual C# in Tipi progettoe quindi fare clic su Applicazione Web ASP.NET in modelli.
  4. Nella casella percorso , sostituire WebApplication1 con FormsAuthAd.
  5. Fare clic su OK.
  6. Destro del mouse sul nodo riferimenti in Esplora soluzioni e scegliere Aggiungi riferimento.
  7. Nella scheda .NET nella finestra di dialogo Aggiungi riferimento , fare clic su System.DirectoryServices.dll, fare clic su Selezionae quindi fare clic su OK.

Scrivere il codice di autenticazione

Seguire questi passaggi per creare un nuovo file di classe denominato LdapAuthentication.cs:
  1. Pulsante destro del mouse sul nodo del progetto in Esplora soluzioni, scegliere Aggiungie quindi fare clic su Aggiungi nuovo elemento.
  2. In modelli, fare clic su classe .
  3. Digitare LdapAuthentication.cs nella casella nome e quindi fare clic su Apri.
  4. Con il seguente codice, sostituire il codice esistente nel file LdapAuthentication.cs.
    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();
    }
    }
    }

Il codice di autenticazione accetta un dominio, un nome utente, password e un percorso per la struttura ad albero in Active Directory. Questo codice utilizza il provider di directory LDAP.

Nella pagina Logon. aspx il codice chiama il metodo LdapAuthentication.IsAuthenticated e passa le credenziali che vengono ottenute dall'utente. Quindi, un oggetto DirectoryEntry viene creato con il percorso di una struttura di directory, il nome utente e la password. Il nome utente deve essere nel formato "dominio\nomeutente". L'oggetto DirectoryEntry tenta di forzare l'associazione oggetto AdsObject ottenendo la proprietà NativeObject . In caso positivo, l'attributo CN per l'utente viene ottenuto mediante la creazione di un oggetto DirectorySearcher e filtrando SAMAccountName. Dopo che l'utente è autenticato, il metodo IsAuthenticated restituisce true.

Per ottenere un elenco di gruppi a cui appartiene l'utente, questo codice chiama il metodo LdapAuthentication.GetGroups . Il metodo LdapAuthentication.GetGroups Ottiene un elenco di gruppi di distribuzione e di protezione che l'utente appartiene a un oggetto DirectorySearcher e filtrando in base all'attributo memberOf . Questo metodo restituisce un elenco di gruppi separati da pipe (|).

Si noti che il metodo LdapAuthentication.GetGroups e modificate tronca le stringhe. Ciò consente di ridurre la lunghezza della stringa memorizzata nel cookie di autenticazione. Se la stringa non è troncata, il formato di ogni gruppo viene visualizzato come segue.
CN=...,...,DC=domain,DC=com
Ciò può creare una stringa molto lunga. Se la lunghezza di questa stringa è maggiore della lunghezza del cookie, i browser potrebbero non accettare il cookie di autenticazione e si verrà reindirizzati alla pagina di accesso. Tuttavia, se si è in un ambiente multidominio, potrebbe essere necessario mantenere il nome di dominio con il nome del gruppo, dal momento che i gruppi in domini diversi possono avere lo stesso nome di gruppo. È necessario mantenere il nome di dominio per distinguere un gruppo da un altro.

La maggior parte dei browser supporta cookie fino a 4096 byte. Se questa stringa potenzialmente può superare la lunghezza del cookie, si consiglia di memorizzare le informazioni sul gruppo nell'oggetto Cache ASP.NET o in un database. In alternativa, è possibile crittografare le informazioni sul gruppo e memorizzare queste informazioni in un campo modulo nascosto.

Scrivere il codice di Global. asax

Il codice nel file Global. asax fornisce un gestore eventi Application_AuthenticateRequest . Il gestore eventi recupera il cookie di autenticazione dall'insieme Context.Request.Cookies , consente di decrittografare il cookie e recupera l'elenco dei gruppi che verranno memorizzati nella proprietà FormsAuthenticationTicket.UserData . I gruppi vengono visualizzati in un elenco separato da pipe che viene creato nella pagina Logon. aspx.

Il codice analizza la stringa in una matrice di stringhe per creare un oggetto GenericPrincipal . Dopo aver creato l'oggetto GenericPrincipal , questo oggetto è posizionato nella proprietà HttpContext. User .
  1. In Esplora soluzioni fare Global. asaxe quindi scegliere Visualizza codice.
  2. Aggiungere il codice seguente all'inizio del file Global.asax.cs code-behind:
    using System.Web.Security;using System.Security.Principal;

  3. Sostituire il gestore eventi vuoto esistente per il Application_AuthenticateRequest con il codice riportato di seguito.
    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;

    }

Modificare il file Web. config

In questa sezione, si configura il < form >, < autenticazione >e gli elementi < autorizzazione > nel file Web. config. Con queste modifiche, solo gli utenti autenticati possono accedere all'applicazione e le richieste non autenticate vengono reindirizzate alla pagina Logon. aspx. È possibile modificare questa configurazione per consentire solo a determinati utenti e gruppi l'accesso all'applicazione.

Sostituire il codice esistente nel file Web. config con il codice riportato di seguito.
<?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>

Si noti il < identity impersonate = "true" / > elemento di configurazione. In questo modo ASP.NET rappresentare l'account configurato come account anonimo da Microsoft Internet Information Services (IIS). In seguito a questa configurazione, tutte le richieste in questa applicazione eseguito nel contesto di protezione dell'account configurato. Fornisce le credenziali per l'autenticazione di Active Directory, ma l'account che accede ad Active Directory è l'account configurato. Per ulteriori informazioni, vedere la sezione riferimenti .

Configurare IIS per l'autenticazione anonima

Per configurare IIS per l'autenticazione anonima, attenersi alla seguente procedura:
  1. In IIS, espandere il nodo del computer del server, siti Web, espandere sito Web predefinito, fare FormsAuthAde quindi scegliere proprietà.
  2. Scegliere la Scheda Protezione Directorye quindi fare clic su Modifica in controllo autenticazione e accesso anonimo.
  3. Rendere l'account anonimo per l'applicazione di un account che dispone dell'autorizzazione di Active Directory.
  4. Fare clic per deselezionare la casella di controllo Consenti per controllo Password di IIS.
  5. Nella sezione "Accesso autenticato", deselezionare la casella di controllo "Autenticazione integrata di Windows".
  6. Fare clic su OK.
  7. Fare clic su Applica
Account IUSR _nomecomputer predefinito non dispone dell'autorizzazione di Active Directory.

Creare la pagina Logon. aspx

Seguire questi passaggi per creare un nuovo modulo Web ASP.NET denominata Logon. aspx:
  1. Destro del mouse sul nodo del progetto in Esplora soluzioni, scegliere Aggiungie quindi fare clic su Aggiungi Web Form.
  2. Digitare Logon. aspx nella casella nome e quindi fare clic su Apri.
  3. In Esplora soluzioni fare Logon. aspxe quindi fare clic su Visualizza finestra di progettazione.
  4. Fare clic sulla scheda HTML nella finestra di progettazione.
  5. Sostituire il codice esistente con il codice riportato di seguito.
    <%@ 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. Modificare il percorso della pagina Logon. aspx in modo che punti al server di Directory LDAP.
La pagina Logon. aspx è una pagina che raccoglie le informazioni dall'utente e chiamare metodi sulla classe LdapAuthentication . Dopo il codice autentica l'utente e ottiene un elenco di gruppi, il codice crea un oggetto FormsAuthenticationTicket , consente di crittografare il ticket, aggiunge il ticket crittografato in un cookie, il cookie viene aggiunto all'insieme di HttpResponse. Cookies e quindi la richiesta viene reindirizzata all'URL richiesto originariamente.

Modificare la pagina WebForm1. aspx

La pagina WebForm1. aspx è la pagina richiesta originariamente. Quando l'utente richiede la pagina, la richiesta viene reindirizzata alla pagina Logon. aspx. Dopo la richiesta viene autenticata, la richiesta viene reindirizzata alla pagina WebForm1. aspx.
  1. In Esplora soluzioni fare WebForm1. aspxe quindi fare clic su Visualizza finestra di progettazione.
  2. Fare clic sulla scheda HTML nella finestra di progettazione.
  3. Sostituire il codice esistente con il codice riportato di seguito.
    <%@ 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. Salvare tutti i file e quindi compilare il progetto.
  5. Richiedere la pagina WebForm1. aspx. Si noti che si viene reindirizzati a Logon. aspx.
  6. Digitare le credenziali di accesso e quindi fare clic su Invia. Quando si viene reindirizzati a WebForm1. aspx, si noti che viene visualizzato il nome utente e tale LdapAuthentication è il tipo di autenticazione per la proprietà Context.User.AuthenticationType .
Nota: Microsoft consiglia di utilizzare la crittografia Secure Sockets Layer (SSL) quando si utilizza l'autenticazione basata su form. In questo modo l'utente viene identificato in base al cookie di autenticazione e crittografia SSL in questa applicazione consente di evitare di compromettere il cookie di autenticazione e altre preziose informazioni trasmesse.

Riferimenti

Per ulteriori informazioni, fare clic sui numeri per visualizzare gli articoli della Microsoft Knowledge Base:

Cenni preliminari sulla protezione ASP.NET 306590

Identità di processo e richiesta 317012 in ASP.NET

311495 come implementare la protezione basata sui ruoli con autenticazione basata su form in un'applicazione ASP.NET utilizzando Visual C# .NET

Come creare chiavi tramite Visual Basic .NET per l'utilizzo di autenticazione basata su form 313091

313116 richieste di autenticazione form non vengono indirizzate alla pagina loginUrl

Proprietà

ID articolo: 316748 - Ultima revisione: 30 gen 2017 - Revisione: 1

Feedback