Condividi tramite


Panoramica dell'autenticazione basata su form (C#)

di Scott Mitchell

Annotazioni

Poiché questo articolo è stato scritto, i provider di appartenenza ASP.NET sono stati sostituiti da ASP.NET Identity. Si raccomanda fortemente di aggiornare le app per usare la piattaforma ASP.NET Identity anziché i provider di Membership presenti al momento della scrittura di questo articolo. ASP.NET Identity offre numerosi vantaggi rispetto al sistema di appartenenza ASP.NET, tra cui :

  • Prestazioni migliori
  • Estendibilità e testbilità migliorate
  • Supporto per OAuth, OpenID Connect e autenticazione a due fattori
  • Supporto delle identità basate sulle attestazioni
  • Migliore interoperabilità con ASP.Net Core

Scarica Codice o Scarica PDF

In questo tutorial passeremo dalla semplice discussione all'implementazione; In particolare, esamineremo l'implementazione dell'autenticazione basata su form. L'applicazione Web che iniziamo a costruire in questa esercitazione continuerà a essere compilata nelle esercitazioni successive, man mano che passiamo dalla semplice autenticazione basata su form all'appartenenza e ai ruoli.

Per ulteriori informazioni su questo argomento: Utilizzo dell'autenticazione basata su form di base in ASP.NET, vedere questo video.

Introduzione

Nell'esercitazione precedente sono state illustrate le varie opzioni di autenticazione, autorizzazione e account utente fornite da ASP.NET. In questo tutorial passeremo dalla semplice discussione all'implementazione; In particolare, esamineremo l'implementazione dell'autenticazione basata su form. L'applicazione Web che iniziamo a costruire in questa esercitazione continuerà a essere compilata nelle esercitazioni successive, man mano che passiamo dalla semplice autenticazione basata su form all'appartenenza e ai ruoli.

Questa esercitazione inizia con un'analisi approfondita del flusso di lavoro di autenticazione basata su form, un argomento toccato nell'esercitazione precedente. Successivamente, verrà creato un sito Web ASP.NET tramite il quale eseguire una dimostrazione dei concetti di autenticazione basata su form. Successivamente, configureremo il sito per l'utilizzo dell'autenticazione basata su form, creeremo una semplice pagina di accesso e vedremo come determinare, nel codice, se un utente è autenticato e, in tal caso, il nome utente con cui ha effettuato l'accesso.

La comprensione del flusso di lavoro di autenticazione basata su form, l'abilitazione in un'applicazione Web e la creazione delle pagine di accesso e disconnessione sono tutti passaggi fondamentali nella creazione di un'applicazione ASP.NET che supporti gli account utente e autentichi gli utenti tramite una pagina Web. Per questo motivo, e poiché queste esercitazioni si basano l'una sull'altra, è consigliabile eseguire questa esercitazione in modo completo prima di passare a quella successiva, anche se si è già esperienza nella configurazione dell'autenticazione basata su form in progetti precedenti.

Informazioni sul flusso di lavoro di autenticazione basata su form

Quando il runtime ASP.NET elabora una richiesta per una risorsa ASP.NET, ad esempio una pagina ASP.NET o un servizio Web ASP.NET, la richiesta genera una serie di eventi durante il ciclo di vita. Ci sono eventi generati all'inizio e alla fine della richiesta, quelli generati quando la richiesta viene autenticata e autorizzata, un evento generato nel caso di un'eccezione non gestita e così via. Per visualizzare un elenco completo degli eventi, fare riferimento agli eventi dell'oggetto HttpApplication.

I moduli HTTP sono classi gestite il cui codice viene eseguito in risposta a un particolare evento nel ciclo di vita della richiesta. ASP.NET viene fornito con una serie di moduli HTTP che eseguono attività essenziali dietro le quinte. Due moduli HTTP integrati che sono particolarmente rilevanti per la nostra discussione sono:

  • FormsAuthenticationModule : autentica l'utente esaminando il ticket di autenticazione basata su form, che in genere è incluso nella raccolta di cookie dell'utente. Se non è presente alcun ticket di autenticazione basata su form, l'utente è anonimo.
  • UrlAuthorizationModule : determina se l'utente corrente è autorizzato o meno ad accedere all'URL richiesto. Questo modulo determina l'autorizzazione consultando le regole di autorizzazione specificate nei file di configurazione dell'applicazione. ASP.NET include anche l'autorità FileAuthorizationModule che determina consultando gli ACL dei file richiesti.

I FormsAuthenticationModule tentativi di autenticare l'utente prima dell'esecuzione UrlAuthorizationModule (e FileAuthorizationModule). Se l'utente che effettua la richiesta non è autorizzato ad accedere alla risorsa richiesta, il modulo di autorizzazione termina la richiesta e restituisce uno stato HTTP 401 Non autorizzato . Negli scenari di autenticazione di Windows, lo stato HTTP 401 viene restituito al browser. Questo codice di stato fa sì che il browser richieda all'utente le credenziali tramite una finestra di dialogo modale. Con l'autenticazione basata su form, tuttavia, lo stato HTTP 401 Non autorizzato non viene mai inviato al browser perché FormsAuthenticationModule rileva questo stato e lo modifica per reindirizzare l'utente alla pagina di accesso (tramite uno stato di reindirizzamento HTTP 302 ).

La responsabilità della pagina di accesso è determinare se le credenziali dell'utente sono valide e, in caso affermativo, creare un ticket di autenticazione basata su form e reindirizzare l'utente alla pagina che stava tentando di visitare. Il ticket di autenticazione è incluso nelle successive richieste alle pagine del sito web, che vengono FormsAuthenticationModule utilizzate per identificare l'utente.

Flusso di lavoro di autenticazione basata su form

Figura 1: Flusso di lavoro di autenticazione basata su form

Ricordare il ticket di autenticazione tra le visite alla pagina

Dopo l'accesso, il ticket di autenticazione basata su form deve essere inviato nuovamente al server Web a ogni richiesta, in modo che l'utente rimanga connesso durante l'esplorazione del sito. Questa operazione viene in genere eseguita inserendo il ticket di autenticazione nella raccolta di cookie dell'utente. I cookie sono piccoli file di testo che risiedono sul computer dell'utente e vengono trasmessi nelle intestazioni HTTP ad ogni richiesta al sito web che ha creato il cookie. Pertanto, una volta che il ticket di autenticazione basata su form è stato creato e memorizzato nei cookie del browser, ogni visita successiva a tale sito invia il ticket di autenticazione insieme alla richiesta, identificando così l'utente.

Un aspetto dei cookie è la loro scadenza, ovvero la data e l'ora in cui il browser elimina il cookie. Alla scadenza del cookie di autenticazione basata su form, l'utente non può più essere autenticato e quindi diventa anonimo. Quando un utente visita da un terminale pubblico, è probabile che desideri che il suo ticket di autenticazione scada quando chiude il browser. Quando si visita da casa, tuttavia, lo stesso utente potrebbe volere che il ticket di autenticazione venga ricordato dopo il riavvio del browser in modo da non dover effettuare nuovamente l'accesso ogni volta che visita il sito. Questa decisione viene spesso presa dall'utente sotto forma di una casella di controllo "Ricordami" nella pagina di accesso. Nel passaggio 3 esamineremo come implementare una casella di controllo "Ricordami" nella pagina di accesso. L'esercitazione seguente illustra in dettaglio le impostazioni di timeout del ticket di autenticazione.

Annotazioni

È possibile che l'agente utente utilizzato per accedere al sito Web non supporti i cookie. In tal caso, ASP.NET possibile utilizzare ticket di autenticazione basata su form senza cookie. In questa modalità, il ticket di autenticazione viene codificato nell'URL. Vedremo quando vengono utilizzati i ticket di autenticazione senza cookie e come vengono creati e gestiti nel prossimo tutorial.

Ambito dell'autenticazione basata su form

Si FormsAuthenticationModule tratta di codice gestito che fa parte del runtime ASP.NET. Prima della versione 7 del server Web Internet Information Services (IIS) di Microsoft, esisteva una barriera distinta tra la pipeline HTTP di IIS e la pipeline del runtime ASP.NET. In breve, in IIS 6 e versioni precedenti, viene FormsAuthenticationModule eseguito solo quando una richiesta viene delegata da IIS al runtime ASP.NET. Per impostazione predefinita, IIS elabora il contenuto statico, ad esempio le pagine HTML e i file CSS e di immagine, e passa le richieste al runtime ASP.NET solo quando viene richiesta una pagina con estensione .aspx, asmx o ashx.

IIS 7, tuttavia, consente IIS integrato e pipeline ASP.NET. Con alcune impostazioni di configurazione è possibile configurare IIS 7 in modo che richiami FormsAuthenticationModule per tutte le richieste. Inoltre, con IIS 7 è possibile definire regole di autorizzazione URL per file di qualsiasi tipo. Per ulteriori informazioni, vedere Modifiche tra la sicurezza di IIS6 e IIS7, Sicurezza della piattaforma Web e Informazioni sull'autorizzazione URL di IIS7.

Per farla breve, nelle versioni precedenti a IIS 7 è possibile utilizzare solo l'autenticazione basata su form per proteggere le risorse gestite dal runtime ASP.NET. Analogamente, le regole di autorizzazione URL vengono applicate solo alle risorse gestite dal runtime ASP.NET. Tuttavia, con IIS 7 è possibile integrare FormsAuthenticationModule e UrlAuthorizationModule nella pipeline HTTP di IIS, estendendo così questa funzionalità a tutte le richieste.

Passaggio 1: creazione di un sito Web ASP.NET per questa serie di tutorial

Al fine di raggiungere il pubblico più ampio possibile, il ASP.NET sito Web che costruiremo nel corso di questa serie sarà creato con la versione gratuita di Visual Studio 2008 di Microsoft, Visual Web Developer 2008. L'archivio SqlMembershipProvider utenti verrà implementato in un database di Microsoft SQL Server 2005 Express Edition . Se si utilizza Visual Studio 2005 o un'edizione diversa di Visual Studio 2008 o SQL Server, non preoccuparsi: i passaggi saranno quasi identici e verranno evidenziate eventuali differenze non banali.

Annotazioni

L'applicazione web demo utilizzata in ogni tutorial è disponibile per il download. Questa applicazione scaricabile è stata creata con Visual Web Developer 2008 per .NET Framework versione 3.5. Poiché l'applicazione è destinata a .NET 3.5, il file Web.config include elementi di configurazione aggiuntivi specifici della versione 3.5. Per farla breve, se devi ancora installare .NET 3.5 sul tuo computer, l'applicazione Web scaricabile non funzionerà senza prima rimuovere il markup specifico di 3.5 da Web.config.

Prima di poter configurare l'autenticazione basata su form, è necessario un sito Web ASP.NET. Inizia creando un nuovo sito Web ASP.NET basato su file system. A tale scopo, avviare Visual Web Developer, quindi scegliere Nuovo sito Web dal menu File, visualizzando la finestra di dialogo Nuovo sito Web. Scegliere il modello di sito Web ASP.NET, impostare l'elenco a discesa Percorso su File System, scegliere una cartella in cui inserire il sito Web e impostare il linguaggio su C#. In questo modo verrà creato un nuovo sito Web con una pagina Default.aspx ASP.NET, una cartella App_Data e un file Web.config.

Annotazioni

Visual Studio supporta due modalità di gestione dei progetti: progetti di sito Web e progetti di applicazione Web. I progetti di sito Web non dispongono di un file di progetto, mentre i progetti di applicazione Web simulano l'architettura del progetto in Visual Studio .NET 2002/2003: includono un file di progetto e compilano il codice sorgente del progetto in un singolo assembly, che viene inserito nella cartella /bin. Inizialmente Visual Studio 2005 supportava solo i progetti di sito Web, anche se il modello di progetto di applicazione Web è stato reintrodotto con il Service Pack 1. Visual Studio 2008 offre entrambi i modelli di progetto. Le edizioni 2005 e 2008 di Visual Web Developer, tuttavia, supportano solo i progetti di sito Web. Utilizzerò il modello del progetto del sito Web. Se si utilizza un'edizione non Express e si desidera utilizzare il modello di progetto applicazione Web , è possibile eseguire questa operazione, ma tenere presente che potrebbero verificarsi alcune discrepanze tra ciò che viene visualizzato sullo schermo e i passaggi da eseguire rispetto alle schermate visualizzate e alle istruzioni fornite in queste esercitazioni.

Crea un nuovo file per il sito Web System-Based

Figura 2: Creazione di un nuovo file System-Based sito Web (fare clic per visualizzare l'immagine a dimensione intera)

Aggiunta di una pagina master

Aggiungere quindi una nuova pagina master al sito nella directory principale denominata Site.master. Le pagine master consentono a uno sviluppatore di pagine di definire un modello a livello di sito che può essere applicato a ASP.NET pagine. Il vantaggio principale delle pagine master è che l'aspetto generale del sito può essere definito in un'unica posizione, semplificando così l'aggiornamento o la modifica del layout del sito.

Aggiungere una pagina master denominata Site.master al sito Web

Figura 3: Aggiunta di una pagina master denominata Site.master al sito Web (fare clic per visualizzare l'immagine a dimensione intera)

Definite il layout di pagina a livello di sito qui nella pagina master. È possibile utilizzare la visualizzazione Progettazione e aggiungere tutti i controlli Layout o Web necessari oppure aggiungere manualmente il markup manualmente nella visualizzazione Origine. Ho strutturato il layout della pagina master in modo da imitare il layout utilizzato nella serie di esercitazioni Utilizzo dei dati in ASP.NET 2.0 (vedere la Figura 4). La pagina master utilizza fogli di stile CSS per il posizionamento e gli stili con le impostazioni CSS definite nel file Style.css (incluso nel download associato a questa esercitazione). Anche se non è possibile dirlo dal markup mostrato di seguito, le regole CSS sono definite in modo tale che il contenuto del div< di navigazione >sia posizionato in modo assoluto in modo da apparire a sinistra e abbia una larghezza fissa di 200 pixel.

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Site.master.cs" Inherits="Site" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Forms Authentication, Authorization, and User Accounts</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id="wrapper">
        <form id="form1" runat="server">
        
            <div id="header">
                <span class="title">User Account Tutorials</span>
            </div>
        
            <div id="content">
                <asp:contentplaceholder id="MainContent" runat="server">
                  <!-- Page-specific content will go here... -->
                </asp:contentplaceholder>
            </div>
            
            <div id="navigation">
                TODO: Menu will go here...
            </div>
        </form>
    </div>
</body>
</html>

Una pagina master definisce sia il layout di pagina statico che le aree che possono essere modificate dalle ASP.NET pagine che utilizzano la pagina master. Queste aree modificabili del ContentPlaceHolder contenuto sono indicate dal controllo, che può essere visualizzato all'interno del div< del contenuto>. La pagina master ha un singolo ContentPlaceHolder (MainContent), ma le pagine master possono avere più ContentPlaceHolders.

Con il markup immesso in precedenza, il passaggio alla vista Progettazione mostra il layout della pagina master. Tutte le pagine ASP.NET che utilizzano questa pagina master avranno questo layout uniforme, con la possibilità di specificare il markup per l'area MainContent .

La pagina master, se visualizzata tramite la vista Progettazione

Figura 4: La pagina master, se visualizzata attraverso la vista Progettazione (fare clic per visualizzare l'immagine a dimensione intera)

Creazione di pagine di contenuto

A questo punto abbiamo una pagina Default.aspx nel nostro sito web, ma non utilizza la pagina master che abbiamo appena creato. Sebbene sia possibile modificare il markup dichiarativo di una pagina Web per utilizzare una pagina master, se la pagina non contiene ancora alcun contenuto è più semplice eliminare la pagina e aggiungerla nuovamente al progetto, specificando la pagina master da utilizzare. Pertanto, inizia eliminando Default.aspx dal progetto.

Fare quindi clic con il pulsante destro del mouse sul nome del progetto in Esplora soluzioni e scegliere di aggiungere un nuovo modulo Web denominato Default.aspx. Questa volta, selezionare la casella di controllo "Seleziona pagina master" e scegliere la pagina master Site.master dall'elenco.

Aggiunta di una nuova pagina Default.aspx Scelta di selezionare una pagina mastro

Figura 5: Aggiunta di una nuova pagina Default.aspx Scelta di selezionare una pagina master (fare clic per visualizzare l'immagine a dimensione intera)

Utilizzare la pagina master Site.master

Figura 6: Utilizzo della pagina master Site.master

Annotazioni

Se si utilizza il modello di progetto Applicazione Web, la finestra di dialogo Aggiungi nuovo elemento non include una casella di controllo "Seleziona pagina master". Invece, è necessario aggiungere un elemento di tipo "Modulo contenuto Web". Dopo aver scelto l'opzione "Modulo contenuto Web" e aver fatto clic su Aggiungi, Visual Studio visualizzerà la stessa finestra di dialogo Seleziona un master illustrata nella Figura 6.

Il markup dichiarativo della nuova pagina Default.aspx include solo una @Page direttiva che specifica il percorso del file della pagina master e un controllo Content per il MainContent ContentPlaceHolder della pagina master.

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>

Per ora, lascia Default.aspx vuoto. Torneremo su di esso più avanti in questo tutorial per aggiungere contenuto.

Annotazioni

La pagina master include una sezione per un menu o un'altra interfaccia di navigazione. Creeremo un'interfaccia di questo tipo in un prossimo tutorial.

Passaggio 2: Abilitazione dell'autenticazione basata su form

Dopo aver creato il ASP.NET sito Web, l'attività successiva consiste nell'abilitare l'autenticazione basata su form. La configurazione di autenticazione dell'applicazione viene specificata tramite l'elemento<authentication> in Web.config. L'elemento <authentication> contiene un singolo attributo denominato mode che specifica il modello di autenticazione utilizzato dall'applicazione. Questo attributo può avere uno dei quattro valori seguenti:

  • Windows : come illustrato nell'esercitazione precedente, quando un'applicazione utilizza l'autenticazione di Windows, è responsabilità del server Web autenticare il visitatore, e questa operazione viene in genere eseguita tramite l'autenticazione di base di Windows, digest o integrata.
  • Moduli: gli utenti vengono autenticati tramite un modulo su una pagina web.
  • Passport: gli utenti vengono autenticati utilizzando la rete Passport di Microsoft.
  • Nessuno: non viene utilizzato alcun modello di autenticazione; Tutti i visitatori sono anonimi.

Per impostazione predefinita, ASP.NET applicazioni utilizzano l'autenticazione di Windows. Per modificare il tipo di autenticazione in autenticazione basata su form, quindi, è necessario modificare l'attributo <authentication> mode dell'elemento in Forms.

Se il progetto non contiene ancora un file di Web.config, aggiungerne uno facendo clic con il pulsante destro del mouse sul nome del progetto in Esplora soluzioni, scegliendo Aggiungi nuovo elemento e quindi aggiungendo un file di configurazione Web.

Se il tuo progetto non include ancora Web.config, aggiungilo ora

Figura 7: Se il tuo progetto non include ancora Web.config, aggiungilo ora (fai clic per visualizzare l'immagine a dimensione intera)

Individuare quindi l'elemento e aggiornarlo per l'utilizzo dell'autenticazione <authentication> basata su form. Dopo questa modifica, il markup del file Web.config dovrebbe essere simile al seguente:

<configuration>
    <system.web>
        ... Unrelated configuration settings and comments removed for brevity ...
        <!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
        -->
        <authentication mode="Forms" />
    </system.web>
</configuration>

Annotazioni

Poiché Web.config è un file XML, l'uso di maiuscole e minuscole è importante. Assicurati di impostare l'attributo mode su Forms, con una "F" maiuscola. Se si utilizza una combinazione di maiuscole e minuscole diversa, ad esempio "moduli", si riceverà un errore di configurazione quando si visita il sito tramite un browser.

L'elemento <authentication> può facoltativamente includere un <forms> elemento figlio che contiene impostazioni specifiche dell'autenticazione basata su form. Per il momento, usiamo solo le impostazioni predefinite di autenticazione basata su form. Esploreremo l'elemento <forms> figlio in modo più dettagliato nell'esercitazione successiva.

Passaggio 3: creazione della pagina di accesso

Per supportare l'autenticazione basata su form, il nostro sito Web necessita di una pagina di accesso. Come illustrato nella sezione "Informazioni sul flusso di lavoro di autenticazione basata su form", l'utente FormsAuthenticationModule verrà reindirizzato automaticamente alla pagina di accesso se tenta di accedere a una pagina che non è autorizzato a visualizzare. Esistono anche controlli Web ASP.NET che mostreranno un collegamento alla pagina di accesso agli utenti anonimi. Questo pone la domanda: "Qual è l'URL della pagina di accesso?"

Per impostazione predefinita, il sistema di autenticazione basata su form prevede che la pagina di accesso venga denominata Login.aspx e inserita nella directory radice dell'applicazione Web. Se si desidera utilizzare un URL della pagina di accesso diverso, è possibile farlo specificandolo in Web.config. Vedremo come farlo nel tutorial successivo.

La pagina di accesso ha tre responsabilità:

  1. Fornire un'interfaccia che consenta al visitatore di inserire le proprie credenziali.
  2. Determinare se le credenziali inviate sono valide.
  3. "Accedere" all'utente creando il ticket di autenticazione basata su form.

Creazione dell'interfaccia utente della pagina di accesso

Iniziamo con la prima attività. Aggiungere una nuova pagina ASP.NET alla directory principale del sito denominata Login.aspx e associarla alla pagina master Site.master.

Aggiungi una nuova pagina ASP.NET denominata Login.aspx

Figura 8: Aggiunta di una nuova pagina ASP.NET denominata Login.aspx (fare clic per visualizzare l'immagine a dimensione intera)

L'interfaccia tipica della pagina di accesso è composta da due caselle di testo, una per il nome dell'utente, una per la password, e un pulsante per inviare il modulo. I siti Web spesso includono una casella di controllo "Ricordami" che, se selezionata, mantiene il ticket di autenticazione risultante dopo il riavvio del browser.

Aggiungere due caselle di testo a Login.aspx e impostarne ID le proprietà rispettivamente su UserName e Password. Impostare anche la proprietà di TextMode Password su Password. Aggiungere quindi un controllo CheckBox, impostando la relativa ID proprietà su RememberMe e la relativa Text proprietà su "Remember Me". Successivamente, aggiungi un pulsante denominato LoginButton la cui Text proprietà è impostata su "Login". Infine, aggiungere un controllo Web Label e impostarne ID la proprietà su InvalidCredentialsMessage, la proprietà Text su "Il nome utente o la password non sono validi. Riprovare.", la proprietà ForeColor è Red e la proprietà Visible è False.

A questo punto la schermata dovrebbe essere simile alla schermata nella Figura 9 e la sintassi dichiarativa della pagina dovrebbe essere simile alla seguente:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
    <h1>
        Login</h1>
    <p>
        Username:
        <asp:TextBox ID="UserName" runat="server"></asp:TextBox></p>
    <p>
        Password:
        <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox></p>
    <p>
        <asp:CheckBox ID="RememberMe" runat="server" Text="Remember Me" /> </p>
    <p>
        <asp:Button ID="LoginButton" runat="server" Text="Login" OnClick="LoginButton_Click" /> </p>
    <p>
        <asp:Label ID="InvalidCredentialsMessage" runat="server" ForeColor="Red" Text="Your username or password is invalid. Please try again."
            Visible="False"></asp:Label> </p>
</asp:Content>

La pagina di accesso contiene due caselle di testo, una casella di controllo, un pulsante e un'etichetta

Figura 9: La pagina di accesso contiene due caselle di testo, una casella di controllo, un pulsante e un'etichetta (fare clic per visualizzare l'immagine a dimensione intera)

Infine, creare un gestore eventi per l'evento Click di LoginButton. Dalla finestra di progettazione è sufficiente fare doppio clic sul controllo Button per creare questo gestore eventi.

Determinazione della validità delle credenziali fornite

A questo punto è necessario implementare l'attività 2 nel gestore dell'evento Click del pulsante, determinando se le credenziali fornite sono valide. A tale scopo, è necessario che sia presente un archivio utenti che contenga tutte le credenziali degli utenti, in modo da poter determinare se le credenziali fornite corrispondono a quelle note.

Prima dell'ASP.NET 2.0, gli sviluppatori erano responsabili dell'implementazione dei propri archivi utente e della scrittura del codice per convalidare le credenziali fornite rispetto all'archivio. La maggior parte degli sviluppatori implementa l'archivio utenti in un database, creando una tabella denominata Users con colonne come UserName, Password, Email, LastLoginDate e così via. Questa tabella, quindi, avrebbe un record per ogni account utente. La verifica delle credenziali fornite da un utente comporta l'interrogazione del database per ottenere un nome utente corrispondente e quindi assicurarsi che la password nel database corrisponda alla password fornita.

Con ASP.NET 2.0, gli sviluppatori devono utilizzare uno dei provider di appartenenze per gestire l'archivio utenti. In questa serie di esercitazioni verrà utilizzato SqlMembershipProvider, che utilizza un database SQL Server per l'archivio utenti. Quando si utilizza SqlMembershipProvider, è necessario implementare uno schema di database specifico che includa le tabelle, le viste e le stored procedure previste dal provider. Verrà esaminato come implementare questo schema nell'esercitazione Creazione dello schema di appartenenza in SQL Server . Con il provider di appartenenze, la convalida delle credenziali dell'utente è semplice come chiamare il metodo ValidateUser(username, password) della classe di appartenenza, che restituisce un valore booleano che indica se la validità della combinazione di nome utente e password. Poiché l'archivio utenti di SqlMembershipProvider non è ancora stato implementato, al momento non è possibile utilizzare il metodo ValidateUser della classe Membership.

Anziché dedicare del tempo alla creazione di una tabella di database Users personalizzata (che sarebbe obsoleta una volta implementato SqlMembershipProvider), è possibile impostare come hardcoded le credenziali valide all'interno della pagina di accesso stessa. Nel gestore dell'evento Click di LoginButton aggiungere il codice seguente:

protected void LoginButton_Click(object sender, EventArgs e)
{
    // Three valid username/password pairs: Scott/password, Jisun/password, and Sam/password.
    string[] users = { "Scott", "Jisun", "Sam" };
    string[] passwords = { "password", "password", "password" };
    for (int i = 0; i < users.Length; i++)
    {
        bool validUsername = (string.Compare(UserName.Text, users[i], true) == 0);
        bool validPassword = (string.Compare(Password.Text, passwords[i], false) == 0);
        if (validUsername && validPassword)
        {
            // TODO: Log in the user...
            // TODO: Redirect them to the appropriate page
        }
    }
    // If we reach here, the user's credentials were invalid
    InvalidCredentialsMessage.Visible = true;
}

Come puoi vedere, ci sono tre account utente validi – Scott, Jisun e Sam – e tutti e tre hanno la stessa password ("password"). Il codice scorre le matrici di utenti e password alla ricerca di una corrispondenza valida tra nome utente e password. Se sia il nome utente che la password sono validi, dobbiamo effettuare il login dell'utente e poi reindirizzarlo alla pagina appropriata. Se le credenziali non sono valide, viene visualizzata l'etichetta InvalidCredentialsMessage.

Quando un utente inserisce credenziali valide, ho detto che viene poi reindirizzato alla "pagina appropriata". Qual è la pagina appropriata, però? Tenere presente che quando un utente visita una pagina che non è autorizzato a visualizzare, FormsAuthenticationModule lo reindirizza automaticamente alla pagina di accesso. In questo modo, include l'URL richiesto nella stringa di query tramite il parametro ReturnUrl. In altre parole, se un utente tenta di visitare ProtectedPage.aspx e non è autorizzato a farlo, FormsAuthenticationModule lo reindirizza a:

Login.aspx? ReturnUrl=ProtectedPage.aspx

Dopo aver effettuato correttamente l'accesso, l'utente deve essere reindirizzato a ProtectedPage.aspx. In alternativa, gli utenti possono visitare la pagina di accesso di propria volontà. In tal caso, dopo aver effettuato l'accesso, l'utente dovrebbe essere inviato alla pagina Default.aspx della cartella principale.

Accesso dell'utente

Supponendo che le credenziali fornite siano valide, è necessario creare un ticket di autenticazione basata su form, consentendo così l'accesso dell'utente al sito. La classe FormsAuthentication nello spazio dei nomi System.Web.Security fornisce diversi metodi per l'accesso e la disconnessione degli utenti tramite il sistema di autenticazione basata su form. Sebbene esistano diversi metodi nella classe FormsAuthentication, i tre che ci interessano in questo frangente sono:

  • GetAuthCookie(username, persistCookie): crea un ticket di autenticazione basata su form per il nome utente specificato. Successivamente, questo metodo crea e restituisce un oggetto HttpCookie che contiene il contenuto del ticket di autenticazione. Se persistCookie è true, viene creato un cookie persistente.
  • SetAuthCookie(username, persistCookie): chiama il metodo GetAuthCookie(username, persistCookie) per generare il cookie di autenticazione basata su form. Questo metodo aggiunge quindi il cookie restituito da GetAuthCookie all'insieme Cookies (presupponendo che venga utilizzata l'autenticazione basata su moduli basata su cookie; in caso contrario, questo metodo chiama una classe interna che gestisce la logica del ticket senza cookie).
  • RedirectFromLoginPage(username, persistCookie): questo metodo chiama SetAuthCookie(username, persistCookie) e quindi reindirizza l'utente alla pagina appropriata.

GetAuthCookie è utile quando è necessario modificare il ticket di autenticazione prima di scrivere il cookie nella raccolta Cookies. SetAuthCookie è utile se si desidera creare il ticket di autenticazione basata su form e aggiungerlo alla raccolta Cookies, ma non si desidera reindirizzare l'utente alla pagina appropriata. Forse vuoi tenerli nella pagina di accesso o inviarli a una pagina alternativa.

Dal momento che vogliamo accedere all'utente e reindirizzarlo alla pagina appropriata, utilizziamo RedirectFromLoginPage. Aggiornare il gestore dell'evento Click di LoginButton, sostituendo le due righe TODO commentate con la riga di codice seguente:

FormsAuthentication.RedirectFromLoginPage(UserName.Text, RememberMe.Checked);

Durante la creazione del ticket di autenticazione basata su form, viene utilizzata la proprietà Text della casella di testo UserName per il parametro username del ticket di autenticazione basata su form e lo stato selezionato della casella di controllo RememberMe per il parametro persistCookie .

Per testare la pagina di accesso, visitala in un browser. Inizia inserendo credenziali non valide, come un nome utente di "Nope" e una password di "sbagliato". Dopo aver fatto clic sul pulsante Accedi, verrà eseguito un postback e verrà visualizzata l'etichetta InvalidCredentialsMessage.

L'etichetta InvalidCredentialsMessage viene visualizzata quando si immettono credenziali non valide

Figura 10: L'etichetta InvalidCredentialsMessage viene visualizzata quando si immettono credenziali non valide (fare clic per visualizzare l'immagine a dimensione intera)

Quindi, inserisci credenziali valide e fai clic sul pulsante Accedi. In questo caso, quando si verifica il postback, viene creato un ticket di autenticazione basata su form e si viene reindirizzati automaticamente a Default.aspx. A questo punto hai effettuato l'accesso al sito Web, anche se non ci sono segnali visivi che indichino che sei attualmente connesso. Nel passaggio 4 vedremo come determinare in modo programmatico se un utente ha effettuato l'accesso o meno, nonché come identificare l'utente che visita la pagina.

Il passaggio 5 esamina le tecniche per disconnettere un utente dal sito Web.

Protezione della pagina di accesso

Quando l'utente inserisce le proprie credenziali e invia il modulo della pagina di accesso, le credenziali, inclusa la password, vengono trasmesse via Internet al server Web in testo normale. Ciò significa che qualsiasi hacker che annusa il traffico di rete può vedere il nome utente e la password. Per evitare ciò, è essenziale crittografare il traffico di rete utilizzando Secure Socket Layers (SSL). Ciò garantirà che le credenziali (così come il markup HTML dell'intera pagina) siano crittografate dal momento in cui lasciano il browser fino a quando non vengono ricevute dal server web.

A meno che il tuo sito web non contenga informazioni sensibili, dovrai utilizzare SSL solo nella pagina di accesso e in altre pagine in cui la password dell'utente verrebbe altrimenti inviata in rete in testo normale. Non è necessario preoccuparsi di proteggere il ticket di autenticazione basata su form poiché, per impostazione predefinita, è crittografato e firmato digitalmente (per evitare manomissioni). Una discussione più approfondita sulla sicurezza dei ticket di autenticazione basata su form è presentata nell'esercitazione seguente.

Annotazioni

Molti siti web finanziari e medici sono configurati per utilizzare SSL su tutte le pagine accessibili agli utenti autenticati. Se si sta creando un sito Web di questo tipo, è possibile configurare il sistema di autenticazione basata su form in modo che il ticket di autenticazione basata su form venga trasmesso solo tramite una connessione sicura.

Passaggio 4: rilevamento dei visitatori autenticati e determinazione della loro identità

A questo punto abbiamo abilitato l'autenticazione basata su form e creato una pagina di accesso rudimentale, ma dobbiamo ancora esaminare come possiamo determinare se un utente è autenticato o anonimo. In alcuni scenari, potremmo voler visualizzare dati o informazioni diversi a seconda che un utente autenticato o anonimo stia visitando la pagina. Inoltre, spesso abbiamo bisogno di conoscere l'identità dell'utente autenticato.

Aumentiamo la pagina Default.aspx esistente per illustrare queste tecniche. In Default.aspx aggiungere due controlli Panel, uno denominato AuthenticatedMessagePanel e l'altro denominato AnonymousMessagePanel. Aggiungere un controllo Label denominato WelcomeBackMessage nel primo pannello. Nel secondo pannello aggiungere un controllo HyperLink, impostare la relativa proprietà Text su "Log In" e la relativa proprietà NavigateUrl su "~/Login.aspx". A questo punto il markup dichiarativo per Default.aspx dovrebbe essere simile al seguente:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
    <asp:Panel runat="server" ID="AuthenticatedMessagePanel">
        <asp:Label runat="server" ID="WelcomeBackMessage"></asp:Label>
    </asp:Panel>
    
    <asp:Panel runat="Server" ID="AnonymousMessagePanel">
        <asp:HyperLink runat="server" ID="lnkLogin" Text="Log In" NavigateUrl="~/Login.aspx"></asp:HyperLink>
    </asp:Panel>
</asp:Content>

Come avrete probabilmente intuito, l'idea qui è quella di visualizzare solo l'AuthenticatedMessagePanel ai visitatori autenticati e solo l'AnonymousMessagePanel ai visitatori anonimi. Per fare ciò, dobbiamo impostare le proprietà Visible di questi pannelli a seconda che l'utente abbia effettuato l'accesso o meno.

La proprietà Request.IsAuthenticated restituisce un valore booleano che indica se la richiesta è stata autenticata. Immettere il codice seguente nel codice del gestore eventi Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    if (Request.IsAuthenticated)
    {
        WelcomeBackMessage.Text = "Welcome back!";
    
        AuthenticatedMessagePanel.Visible = true;
        AnonymousMessagePanel.Visible = false;
    }
    else
    {
        AuthenticatedMessagePanel.Visible = false;
        AnonymousMessagePanel.Visible = true;
    }
}

Con questo codice in atto, visita Default.aspx tramite un browser. Supponendo che tu debba ancora accedere, vedrai un link alla pagina di accesso (vedi Figura 11). Clicca su questo link e accedi al sito. Come abbiamo visto nel passaggio 3, dopo aver inserito le credenziali verrai riportato a Default.aspx, ma questa volta la pagina mostra il messaggio "Bentornato!" (vedi Figura 12).

Quando si effettua una visita anonima, viene visualizzato un collegamento di accesso

Figura 11: Quando si effettua una visita anonima, viene visualizzato un collegamento di accesso

Agli utenti autenticati viene mostrato il

Figura 12: Agli utenti autenticati viene mostrato il messaggio "Bentornato!" Messaggio

È possibile determinare l'identità dell'utente attualmente connesso tramite la proprietà Userdell'oggetto HttpContext. L'oggetto HttpContext rappresenta le informazioni sulla richiesta corrente ed è la sede di oggetti ASP.NET comuni come Response, Request e Session, tra gli altri. La proprietà User rappresenta il contesto di sicurezza della richiesta HTTP corrente e implementa l'interfaccia IPrincipal.

La proprietà User viene impostata da FormsAuthenticationModule. In particolare, quando FormsAuthenticationModule trova un ticket di autenticazione basata su form nella richiesta in ingresso, crea un nuovo oggetto GenericPrincipal e lo assegna alla proprietà User.

Gli oggetti Principal (ad esempio GenericPrincipal) forniscono informazioni sull'identità dell'utente e sui ruoli a cui appartengono. L'interfaccia IPrincipal definisce due membri:

Possiamo determinare il nome del visitatore corrente utilizzando il seguente codice:

stringa currentUsersName = User.Identity.Name;

Quando si utilizza l'autenticazione basata su form, viene creato un oggetto FormsIdentity per la proprietà Identity di GenericPrincipal. La classe FormsIdentity restituisce sempre la stringa "Forms" per la proprietà AuthenticationType e true per la proprietà IsAuthenticated. La proprietà Name restituisce il nome utente specificato durante la creazione del ticket di autenticazione basata su form. Oltre a queste tre proprietà, FormsIdentity include l'accesso al ticket di autenticazione sottostante tramite la relativa proprietà Ticket. La proprietà Ticket restituisce un oggetto di tipo FormsAuthenticationTicket, con proprietà quali Expiration, IsPersistent, IssueDate, Name e così via.

Il punto importante da tenere presente è che il parametro username specificato nei metodi FormsAuthentication.GetAuthCookie(username, persistCookie), FormsAuthentication.SetAuthCookie(username, persistCookie) e FormsAuthentication.RedirectFromLoginPage(username, persistCookie) è lo stesso valore restituito da User.Identity.Name. Inoltre, il ticket di autenticazione creato con questi metodi è disponibile eseguendo il cast di User.Identity a un oggetto FormsIdentity e quindi accedendo alla proprietà Ticket:

FormsIdentity ident = User.Identity as FormsIdentity;
FormsAuthenticationTicket authTicket = ident.Ticket;

Forniamo un messaggio più personalizzato in Default.aspx. Aggiornare il gestore eventi Page_Load in modo che alla proprietà Text dell'etichetta WelcomeBackMessage venga assegnata la stringa "Bentornato, nome utente!"

WelcomeBackMessage.Text = "Bentornato, " + User.Identity.Name + "!";

La Figura 13 mostra l'effetto di questa modifica (quando si accede come utente Scott).

Il messaggio di benvenuto include il nome dell'utente attualmente connesso

Figura 13: Il messaggio di benvenuto include il nome dell'utente attualmente connesso

Utilizzo dei controlli LoginView e LoginName

La visualizzazione di contenuti diversi a utenti autenticati e anonimi è un requisito comune; Così come viene visualizzato il nome dell'utente attualmente connesso. Per questo motivo, ASP.NET include due controlli Web che forniscono le stesse funzionalità illustrate nella Figura 13, ma senza la necessità di scrivere una singola riga di codice.

Il controllo LoginView è un controllo Web basato su modelli che semplifica la visualizzazione di dati diversi a utenti autenticati e anonimi. LoginView include due modelli predefiniti:

  • AnonymousTemplate: qualsiasi markup aggiunto a questo modello viene visualizzato solo dai visitatori anonimi.
  • LoggedInTemplate: il markup di questo modello viene mostrato solo agli utenti autenticati.

Aggiungiamo il controllo LoginView alla pagina master del nostro sito, Site.master. Anziché aggiungere solo il controllo LoginView, tuttavia, aggiungiamo un nuovo controllo ContentPlaceHolder e quindi inseriamo il controllo LoginView all'interno di tale nuovo ContentPlaceHolder. La logica di questa decisione diventerà evidente a breve.

Annotazioni

Oltre a AnonymousTemplate e LoggedInTemplate, il controllo LoginView può includere modelli specifici del ruolo. I modelli specifici del ruolo mostrano il markup solo agli utenti che appartengono a un ruolo specificato. Esamineremo le funzionalità basate sui ruoli del controllo LoginView in un'esercitazione futura.

Per iniziare, aggiungere un oggetto ContentPlaceHolder denominato LoginContent nella pagina master all'interno dell'elemento div< di navigazione>. È sufficiente trascinare un controllo ContentPlaceHolder dalla Casella degli strumenti alla visualizzazione Origine, posizionando il markup risultante proprio sopra il pulsante "TODO: Menu will go here..." Testo.

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Aggiungere quindi un controllo LoginView all'interno di LoginContent ContentPlaceHolder. Il contenuto inserito nei controlli ContentPlaceHolder della pagina master è considerato contenuto predefinito per ContentPlaceHolder. In altre parole, ASP.NET pagine che utilizzano questa pagina master possono specificare il proprio contenuto per ogni ContentPlaceHolder o utilizzare il contenuto predefinito della pagina master.

LoginView e altri controlli relativi all'accesso si trovano nella scheda Login della Casella degli strumenti.

Controllo LoginView nella Casella degli strumenti

Figura 14: controllo LoginView nella casella degli strumenti

Aggiungere quindi due <elementi br /> immediatamente dopo il controllo LoginView, ma sempre all'interno di ContentPlaceHolder. A questo punto, il markup dell'elemento div< di navigazione >dovrebbe essere simile al seguente:

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
        </asp:LoginView>
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

I modelli di LoginView possono essere definiti dalla finestra di progettazione o dal markup dichiarativo. Dalla finestra di progettazione di Visual Studio espandere lo smart tag di LoginView, che elenca i modelli configurati in un elenco a discesa. Digita il testo "Hello, stranger" in AnonymousTemplate; aggiungere quindi un controllo HyperLink e impostarne le proprietà Text e NavigateUrl rispettivamente su "Log In" e "~/Login.aspx".

Dopo aver configurato l'AnonymousTemplate, passa al LoggedInTemplate e inserisci il testo "Bentornato". Trascinare quindi un controllo LoginName dalla Casella degli strumenti in LoggedInTemplate, posizionandolo immediatamente dopo il testo "Bentornato". Il controllo LoginName, come suggerisce il nome, visualizza il nome dell'utente attualmente connesso. Internamente, il controllo LoginName restituisce semplicemente la proprietà User.Identity.Name

Dopo aver apportato queste aggiunte ai modelli di LoginView, il markup dovrebbe essere simile al seguente:

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
            <LoggedInTemplate>
                Welcome back,
                <asp:LoginName ID="LoginName1" runat="server" />.
            </LoggedInTemplate>
            <AnonymousTemplate>
                Hello, stranger.
                <asp:HyperLink ID="lnkLogin" runat="server" NavigateUrl="~/Login.aspx">Log In</asp:HyperLink>
            </AnonymousTemplate>
        </asp:LoginView>
        
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Con questa aggiunta alla pagina master Site.master, ogni pagina del sito Web visualizzerà un messaggio diverso a seconda che l'utente sia autenticato o meno. La Figura 15 mostra la pagina Default.aspx quando viene visitata tramite un browser dall'utente Jisun. Il messaggio "Bentornato, Jisun" viene ripetuto due volte: una volta nella sezione di navigazione della pagina master a sinistra (tramite il controllo LoginView appena aggiunto) e una volta nell'area del contenuto del Default.aspx (tramite i controlli Panel e la logica a livello di codice).

Viene visualizzato il controllo LoginView

Figura 15: il controllo LoginView visualizza "Bentornato, Jisun".

Poiché LoginView è stato aggiunto alla pagina master, può essere visualizzato in ogni pagina del sito. Tuttavia, potrebbero esserci pagine web in cui non vogliamo mostrare questo messaggio. Una di queste pagine è la pagina di accesso, poiché un collegamento alla pagina di accesso sembra fuori luogo. Poiché il controllo LoginView è stato inserito in un ContentPlaceHolder nella pagina master, è possibile eseguire l'override di questo markup predefinito nella pagina del contenuto. Apri Login.aspx e vai alla finestra di progettazione. Poiché non è stato definito in modo esplicito un controllo Content in Login.aspx per LoginContent ContentPlaceHolder nella pagina master, la pagina di accesso mostrerà il markup predefinito della pagina master per questo ContentPlaceHolder. È possibile visualizzare questa condizione tramite la finestra di progettazione: LoginContent ContentPlaceHolder mostra il markup predefinito (il controllo LoginView).

Nella pagina di accesso viene visualizzato il contenuto predefinito per l'oggetto LoginContent ContentPlaceHolder della pagina master

Figura 16: la pagina di accesso mostra il contenuto predefinito per il LoginContent ContentPlaceHolder della pagina master (fare clic per visualizzare l'immagine a dimensione intera)

Per eseguire l'override del markup predefinito per LoginContent ContentPlaceHolder, è sufficiente fare clic con il pulsante destro del mouse sull'area nella finestra di progettazione e scegliere l'opzione Crea contenuto personalizzato dal menu di scelta rapida. Quando si utilizza Visual Studio 2008, ContentPlaceHolder include uno smart tag che, se selezionato, offre la stessa opzione. In questo modo viene aggiunto un nuovo controllo Content al markup della pagina e quindi è possibile definire il contenuto personalizzato per questa pagina. Potresti aggiungere un messaggio personalizzato qui, come "Effettua l'accesso...", ma lasciamolo vuoto.

Annotazioni

In Visual Studio 2005, la creazione di contenuto personalizzato crea un controllo Content vuoto nella pagina ASP.NET. In Visual Studio 2008, tuttavia, la creazione di contenuto personalizzato consente di copiare il contenuto predefinito della pagina master nel controllo Content appena creato. Se si utilizza Visual Studio 2008, dopo aver creato il nuovo controllo Content, assicurarsi di cancellare il contenuto copiato dalla pagina master.

La Figura 17 mostra la pagina Login.aspx quando viene visitata da un browser dopo aver apportato questa modifica. Si noti che non c'è alcun messaggio "Ciao, sconosciuto" o "Bentornato, nome utente" nel div< di navigazione >a sinistra come quando si visita Default.aspx.

La pagina di accesso nasconde il markup predefinito di LoginContent ContentPlaceHolder

Figura 17: La pagina di accesso nasconde il markup predefinito di LoginContent ContentPlaceHolder (fare clic per visualizzare l'immagine a dimensione intera)

Passaggio 5: disconnessione

Nel passaggio 3 abbiamo esaminato la creazione di una pagina di accesso per consentire a un utente di accedere al sito, ma non abbiamo ancora visto come disconnettere un utente. Oltre ai metodi per l'accesso di un utente, la classe FormsAuthentication fornisce anche un metodo SignOut. Il metodo SignOut elimina semplicemente il ticket di autenticazione basata su form, disconnettendo così l'utente dal sito.

L'offerta di un collegamento di disconnessione è una funzionalità così comune che ASP.NET include un controllo appositamente progettato per disconnettere un utente. Il controllo LoginStatus visualizza un LinkButton "Login" o un LinkButton "Logout", a seconda dello stato di autenticazione dell'utente. Per gli utenti anonimi viene eseguito il rendering di un LinkButton "Accedi", mentre per gli utenti autenticati viene visualizzato un LinkButton "Disconnetti". Il testo per i LinkButton "Login" e "Logout" può essere configurato tramite le proprietà LoginText e LogoutText di LoginStatus.

Facendo clic sul LinkButton "Accedi" si verifica un postback, da cui viene emesso un reindirizzamento alla pagina di accesso. Se si fa clic sul pulsante di collegamento "Disconnetti", il controllo LoginStatus richiama il metodo FormsAuthentication.SignOff e quindi reindirizza l'utente a una pagina. La pagina a cui viene reindirizzato l'utente disconnesso dipende dalla proprietà LogoutAction, che può essere assegnata a uno dei tre valori seguenti:

  • Aggiorna: l'impostazione predefinita; reindirizza l'utente alla pagina che stava appena visitando. Se la pagina che stavano appena visitando non consente utenti anonimi, FormsAuthenticationModule reindirizzerà automaticamente l'utente alla pagina di accesso.

Potresti essere curioso di sapere perché viene eseguito un reindirizzamento qui. Se l'utente vuole rimanere sulla stessa pagina, perché la necessità del reindirizzamento esplicito? Il motivo è che quando si fa clic sul LinkButton "Disconnetti", l'utente ha ancora il ticket di autenticazione basata su form nella raccolta di cookie. Di conseguenza, la richiesta di postback è una richiesta autenticata. Il controllo LoginStatus chiama il metodo SignOut, ma ciò si verifica dopo che FormsAuthenticationModule ha autenticato l'utente. Pertanto, un reindirizzamento esplicito fa sì che il browser richieda nuovamente la pagina. Nel momento in cui il browser richiede nuovamente la pagina, il ticket di autenticazione basata su form è stato rimosso e pertanto la richiesta in ingresso è anonima.

  • Reindirizzamento: l'utente viene reindirizzato all'URL specificato dalla proprietà LogoutPageUrl di LoginStatus.
  • RedirectToLoginPage: l'utente viene reindirizzato alla pagina di accesso.

Aggiungiamo un controllo LoginStatus alla pagina master e configuriamolo per l'utilizzo dell'opzione Reindirizza per inviare l'utente a una pagina che visualizza un messaggio che conferma che è stato disconnesso. Per iniziare, creare una pagina nella directory principale denominata Logout.aspx. Non dimenticare di associare questa pagina alla pagina master Site.master. Successivamente, inserisci un messaggio nel markup della pagina che spieghi all'utente che è stato disconnesso.

Tornare quindi alla pagina master Site.master e aggiungere un controllo LoginStatus sotto LoginView in LoginContent ContentPlaceHolder. Impostare la proprietà LogoutAction del controllo LoginStatus su Reindirizza e la relativa proprietà LogoutPageUrl su "~/Logout.aspx".

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
            <LoggedInTemplate>
                Welcome back,
                <asp:LoginName ID="LoginName1" runat="server" />.
            </LoggedInTemplate>
            <AnonymousTemplate>
                Hello, stranger.
                <asp:HyperLink ID="lnkLogin" runat="server" NavigateUrl="~/Login.aspx">Log In</asp:HyperLink>
            </AnonymousTemplate>
        </asp:LoginView>
        <br />
        <asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="Redirect" LogoutPageUrl="~/Logout.aspx" />
        
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Poiché LoginStatus si trova all'esterno del controllo LoginView, verrà visualizzato sia per gli utenti anonimi che per quelli autenticati, ma questo è possibile perché LoginStatus visualizzerà correttamente un LinkButton "Accedi" o "Disconnetti". Con l'aggiunta del controllo LoginStatus, il collegamento ipertestuale "Accedi" in AnonymousTemplate è superfluo, quindi rimuovilo.

La figura 18 mostra Default.aspx quando Jisun lo visita. Si noti che la colonna di sinistra mostra il messaggio "Bentornato, Jisun" insieme a un link per disconnettersi. Se si fa clic sul LinkButton di disconnessione, viene eseguito il postback, Jisun viene disconnessa dal sistema e quindi viene reindirizzata a Logout.aspx. Come mostra la Figura 19, quando Jisun raggiunge Logout.aspx è già stata disconnessa ed è quindi anonima. Di conseguenza, la colonna di sinistra mostra il testo "Benvenuto, straniero" e un link alla pagina di accesso.

Default.aspx spettacoli

Figura 18: Default.aspx mostra "Bentornato, Jisun" insieme a un pulsante di collegamento "Disconnetti" (fare clic per visualizzare l'immagine a grandezza naturale)

Logout.aspx spettacoli

Figura 19: Logout.aspx mostra "Benvenuto, straniero" insieme a un pulsante di collegamento "Accedi" (fare clic per visualizzare l'immagine a grandezza naturale)

Annotazioni

Ti invito a personalizzare la pagina Logout.aspx per nascondere il LoginContent ContentPlaceHolder della pagina master (come abbiamo fatto per Login.aspx nel passaggio 4). Il motivo è che il LinkButton "Login" di cui è stato eseguito il rendering dal controllo LoginStatus (quello sotto "Hello, stranger") invia l'utente alla pagina di accesso passando l'URL corrente nel parametro querystring ReturnUrl. In breve, se un utente che si è disconnesso fa clic sul LinkButton "Accedi" di questo LoginStatus e quindi effettua l'accesso, verrà reindirizzato a Logout.aspx, il che potrebbe facilmente confondere l'utente.

Riassunto

In questa esercitazione si è iniziato con un esame del flusso di lavoro di autenticazione basata su form e quindi si è passati all'implementazione dell'autenticazione basata su form in un'applicazione ASP.NET. L'autenticazione basata su form è basata su FormsAuthenticationModule, che ha due responsabilità: identificare gli utenti in base al ticket di autenticazione basata su form e reindirizzare gli utenti non autorizzati alla pagina di accesso.

La classe FormsAuthentication di .NET Framework include metodi per la creazione, l'ispezione e la rimozione di ticket di autenticazione basata su form. La proprietà Request.IsAuthenticated e l'oggetto User forniscono ulteriore supporto a livello di codice per determinare se una richiesta è autenticata e informazioni sull'identità dell'utente. Sono inoltre disponibili i controlli Web LoginView, LoginStatus e LoginName, che offrono agli sviluppatori un modo rapido e senza codice per eseguire molte attività comuni correlate all'accesso. Esamineremo questi e altri controlli Web relativi all'accesso in modo più dettagliato nelle esercitazioni future.

In questa esercitazione è stata fornita una panoramica sommaria dell'autenticazione basata su form. Non sono state esaminate le opzioni di configurazione assortite, non è stato esaminato il funzionamento dei ticket di autenticazione basata su form senza cookie o non è stato possibile esplorare il modo in cui ASP.NET protegge il contenuto del ticket di autenticazione basata su form.

Buon programmatori!

Altre informazioni

Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:

Formazione video sugli argomenti contenuti in questa esercitazione

Informazioni sull'autore

Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto a mitchell@4GuysFromRolla.com.

Grazie speciali a...

Questa serie di esercitazioni è stata esaminata da molti revisori competenti. Il revisore principale per questa esercitazione è stato esaminato da molti revisori utili. I revisori potenziali per questa esercitazione includono Alicja Maziarz, John Suru e Teresa Murphy. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.