Autenticazione e autorizzazione

Implementazione di IPrincipal

In questa pagina
ObiettiviObiettivi
Ambito di applicazioneAmbito di applicazione
Utilizzo del moduloUtilizzo del modulo
RiepilogoRiepilogo
Conoscenze necessarieConoscenze necessarie
Creazione di una semplice applicazione WebCreazione di una semplice applicazione Web
Configurazione dell'applicazione Web per l'autenticazione basata su moduliConfigurazione dell'applicazione Web per l'autenticazione basata su moduli
Generazione di un ticket di autenticazione per gli utenti autenticatiGenerazione di un ticket di autenticazione per gli utenti autenticati
Creazione di una classe che implementa ed estende IPrincipalCreazione di una classe che implementa ed estende IPrincipal
Creazione dell'oggetto CustomPrincipalCreazione dell'oggetto CustomPrincipal
Test dell'applicazioneTest dell'applicazione
Altre risorseAltre risorse

Obiettivi

Il modulo consente di:

Creare una classe che implementa l'interfaccia IPrincipal, utilizzabile insieme con la protezione .NET basata sui ruoli.

Ambito di applicazione

Le informazioni contenute in questo modulo sono valide per i seguenti prodotti e tecnologie:

Microsoft Windows® XP o Windows 2000 Server con Service Pack 3 e sistemi operativi successivi

.NET Framework versione 1.0 con Service Pack 2 e versioni successive

Microsoft Visual C#® .NET

Utilizzo del modulo

Per trarre il massimo vantaggio dal modulo:

È necessario aver acquisito esperienza nella programmazione mediante l'utilizzo di Visual C# .NET e Microsoft Visual Studio® .NET.

È necessario aver acquisito esperienza nell'utilizzo dell'ambiente di sviluppo Visual Studio .NET.

È necessario aver acquisito esperienza nello sviluppo di applicazioni Web mediante l'utilizzo di ASP.NET.

Leggere il modulo 3 "Autenticazione e autorizzazione". Vi sono incluse un'introduzione alla protezione .NET basata sui ruoli e una trattazione dell'interfaccia IPrincipal.

Leggere il modulo 8 "Protezione di ASP.NET". Include una trattazione esaustiva di IPrincipal e dell'utilizzo della protezione .NET basata sui ruoli nelle applicazioni Web ASP.NET.

Leggere "Procedura - Utilizzo dell'autenticazione basata su moduli mediante Active Directory". Vengono riportate informazioni dettagliate su come ottenere le informazioni dell'account utente da Active Directory.

Leggere "Procedura - Utilizzo dell'autenticazione basata su moduli mediante SQL Server 2000". Include informazioni dettagliate sulla modalità di utilizzo di SQL ServerTM 2000 come database di account utente.

Riepilogo

Microsoft® .NET Framework fornisce due implementazioni dell'interfaccia IPrincipal: WindowsPrincipal e GenericPrincipal. Questi classi forniscono funzionalità di controllo dell'autorizzazione basata sui ruoli che si dimostrano sufficienti per la maggior parte degli scenari applicativi.

In alcune circostanze, tuttavia, potrebbe essere necessario sviluppare un'implementazione personalizzata di IPrincipal che fornisca funzionalità personalizzate. In questo modulo viene descritto come implementare una classe IPrincipal personalizzata e utilizzarla per l'autorizzazione basata sui ruoli in un'applicazione ASP.NET che implementa l'autenticazione basata su moduli.

Conoscenze necessarie

In .NET Framework sono disponibili le classi WindowsPrincipal e GenericPrincipal, che forniscono la funzionalità di base di controllo dei ruoli rispettivamente per i meccanismi di autenticazione di Windows e non Windows. Entrambe le classi implementano l'interfaccia IPrincipal. Per poter essere utilizzati per l'autorizzazione, ASP.NET esige che tali oggetti vengano archiviati in HttpContext.User. Per le applicazioni basate su Windows, devono essere archiviati in Thread.CurrentPrincipal.

Le funzionalità offerte da queste classi sono sufficienti per la maggior parte degli scenari applicativi. Le applicazioni possono chiamare in modo esplicito il metodo IPrincipal.IsInRole per eseguire i controlli dei ruoli a livello di programmazione. Il metodo Demand della classe PrincipalPermission, se utilizzato per richiedere in modo dichiarativo o imperativo che un chiamante appartenga a un ruolo specifico, determina anche una chiamata a IPrincipal.IsInRole.

In alcuni casi, potrebbe essere necessario sviluppare implementazioni di oggetti Principal personalizzate creando una classe che implementa l'interfaccia IPrincipal. Per l'autorizzazione .NET, è possibile utilizzare qualsiasi classe che implementa IPrincipal.

La classe IPrincipal viene implementata per i seguenti motivi:

Si desidera disporre di una funzionalità estesa di controllo di ruolo. Si preferisce disporre di metodi che consentano di verificare se un determinato utente appartenga a più ruoli. Ad esempio:

CustomPrincipal.IsInAllRoles( "Role1", "Role2", "Role3" ) 
CustomPrincipal.IsInAnyRole( "Role1", "Role2", "Role3" ) 

Si desidera implementare un metodo o una proprietà aggiuntivi che restituiscono un elenco dei ruoli in una matrice. Ad esempio:

string[] roles = CustomPrincipal.Roles; 

Si desidera che l'applicazione adotti una logica gerarchica dei ruoli. Ad esempio, la posizione gerarchica di un Senior Manager potrebbe essere considerata più in alto rispetto a quella di un Manager; Questa condizione può essere verificata utilizzando metodi analoghi ai seguenti:

CustomPrincipal.IsInHigherRole("Manager"); 
CustomPrincipal.IsInLowerRole("Manager"); 

Si desidera implementare un'inizializzazione lazy degli elenchi dei ruoli. Ad esempio, l'elenco dei ruoli potrebbe essere caricato dinamicamente soltanto quando venisse richiesto un controllo di ruolo.

In questo modulo viene descritto come implementare una classe IPrincipal personalizzata e utilizzarla per l'autorizzazione basata sui ruoli in un'applicazione ASP.NET che implementa l'autenticazione basata su moduli.

Creazione di una semplice applicazione Web

Questa procedura consente di creare una nuova applicazione Web ASP.NET. L'applicazione includerà due pagine, ovvero una pagina predefinita alla quale possono accedere solo gli utenti autenticati e una pagina di accesso utilizzate per raccogliere le credenziali degli utenti.

Per creare una semplice applicazione Web

1.

Avviare Visual Studio .NET e creare una nuova applicazione Web ASP.NET C# denominata CustomPrincipalApp.

2.

Rinominare WebForm1.aspx come Logon.aspx.

3.

Aggiungere a Logon.aspx i controlli elencati nella tabella 1 per creare un modulo di accesso.

Tabella 1: controlli di Logon.aspx

Tipo di controlloTestoID

Etichetta

Nome utente:

-

Etichetta

Password

-

Casella di testo

-

txtUserName

Casella di testo

-

txtPassword

Pulsante

Accedi

btnLogon

4.

Impostare la proprietà TextMode del controllo Casella di testo della password su Password.

5.

In Esplora soluzioni fare clic con il pulsante destro del mouse su CustomPrincipalApp, selezionare Aggiungi, quindi fare clic su Aggiungi Web Form.

6.

Immettere default.aspx come nome del nuovo modulo, quindi fare clic su Apri.

Configurazione dell'applicazione Web per l'autenticazione basata su moduli

Per modificare il file web.config dell'applicazione in modo da configurare quest'ultima per l'autenticazione basata su moduli

1.

Utilizzare Esplora soluzioni per aprire il file web.config.

2.

Individuare l'elemento <authentication> e modificare l'attributo mode impostandolo su Forms.

3.

Aggiungere l'elemento <forms> che segue come figlio dell'elemento <authentication> e impostare gli attributi loginUrl, name, timeout e path nel modo seguente:

<authentication mode="Forms"> 
  <forms loginUrl="logon.aspx" name="AuthCookie" timeout="60" path="/"> 
  </forms> 
</authentication> 

4.

Aggiungere l'elemento <authorization> riportato di seguito sotto l'elemento <authentication>. In questo modo, l'accesso all'applicazione verrà consentito solo agli utenti autenticati. L'attributo loginUrl dell'elemento <authentication>, definito in precedenza, reindirizza le richieste non autenticate alla pagina Logon.aspx.

<authorization>  
  <deny users="?" /> 
  <allow users="*" /> 
</authorization> 

Generazione di un ticket di autenticazione per gli utenti autenticati

Questa procedura consente di scrivere il codice per generare un ticket di autenticazione per gli utenti autenticati. Il ticket di autenticazione è un tipo di cookie utilizzato da FormsAuthenticationModule ASP.NET.

Il codice di autenticazione consente generalmente di cercare il nome utente e la password specificati in un database personalizzato o nel servizio Microsoft Active Directory®.

Per informazioni sull'esecuzione di queste ricerche, vedere i seguenti moduli di questa guida:

"Procedura - Utilizzo dell'autenticazione basata su moduli mediante Active Directory"

"Procedura - Utilizzo dell'autenticazione basata su moduli mediante SQL Server 2000"

Per generare un ticket di autenticazione per gli utenti autenticati

1.

Aprire il file Logon.aspx.cs e aggiungere l'istruzione using riportata di seguito all'inizio del file, sotto le istruzioni using esistenti.

using System.Web.Security; 

2.

Aggiungere il metodo dell'helper privato riportato di seguito alla classe WebForm1 denominata IsAuthenticated, utilizzata per convalidare i nomi utente e le password durante l'autenticazione degli utenti. Per questo codice viene presupposto che siano valide tutte le combinazioni di nome utente e password.

private bool IsAuthenticated( string username, string password ) 
{ 
  // Lookup code omitted for clarity 
  // This code would typically validate the user name and password 
  // combination against a SQL database or Active Directory 
  // Simulate an authenticated user 
  return true; 
} 

3.

Aggiungere il metodo dell'helper privato denominato GetRoles riportato di seguito, utilizzato per ottenere l'insieme dei ruoli dell'utente.

private string GetRoles( string username, string password ) 
{ 
  // Lookup code omitted for clarity 
  // This code would typically look up the role list from a database  
  table. 
  // If the user was being authenticated against Active Directory, the 
  // Security groups and/or distribution lists that the user belongs to  
  may 
be  
  // used instead 
  // This GetRoles method returns a pipe delimited string containing roles 
  // rather than returning an array, because the string format is  
  convenient  
  // for storing in the authentication ticket / cookie, as user data 
  return "Senior Manager|Manager|Employee"; 
} 

4.

Visualizzare il modulo Logon.aspx in modalità progettazione, quindi fare doppio clic sul pulsante Accedi per creare un gestore eventi Click.

5.

Aggiungere una chiamata al metodo IsAuthenticated, specificando il nome utente e la password acquisiti tramite il modulo di accesso. Assegnare il valore restituito a una variabile di tipo bool, che indica se l'utente è autenticato o meno.

bool isAuthenticated = IsAuthenticated( txtUserName.Text,  
                                        txtPassword.Text ); 

6.

Se l'utente è autenticato, aggiungere una chiamata al metodo GetRoles per ottenere l'elenco dei ruoli dell'utente.

if (isAuthenticated == true ) 
{ 
  string roles = GetRoles( txtUserName.Text, txtPassword.Text ); 

7.

Creare un nuovo ticket di autenticazione basata su moduli contenente il nome utente, la data di scadenza e l'elenco dei ruoli dell'utente. Si noti che la proprietà User data del ticket di autenticazione viene utilizzata per archiviare l'elenco dei ruoli dell'utente. Osservare inoltre che il codice riportato di seguito consente di creare un ticket non permanente, anche se il fatto che il ticket o cookie sia permanente o meno dipende dallo scenario dell'applicazione specifica.

  // Create the authentication ticket 
  FormsAuthenticationTicket authTicket = new  
       FormsAuthenticationTicket(1,                          // version 
                                 txtUserName.Text,           // user name 
                                 DateTime.Now,               // creation 
                                 DateTime.Now.AddMinutes(60),// Expiration 
                                 false,                      // Persistent 
                                 roles );                    // User data 

8.

Aggiungere il codice per creare una rappresentazione del ticket in formato di stringa crittografata e archiviarla come dati all'interno di un oggetto HttpCookie .

  // Now encrypt the ticket. 
  string encryptedTicket = FormsAuthentication.Encrypt(authTicket); 
  // Create a cookie and add the encrypted ticket to the  
  // cookie as data. 
  HttpCookie authCookie =  
               new HttpCookie(FormsAuthentication.FormsCookieName, 
                              encryptedTicket); 

9.

Aggiungere il cookie all'insieme di cookie restituito al browser dell'utente.

  // Add the cookie to the outgoing cookies collection.  
  Response.Cookies.Add(authCookie);  

10.

Reindirizzare l'utente alla pagina richiesta in origine.

  // Redirect the user to the originally requested page 
  Response.Redirect( FormsAuthentication.GetRedirectUrl( 
                                                txtUserName.Text,  
                                                false )); 
} 

Creazione di una classe che implementa ed estende IPrincipal

Questa procedura consente di creare una classe che implementa l'interfaccia IPrincipal. Consente inoltre di aggiungere altri metodi e proprietà alla classe per fornire funzionalità aggiuntive di autorizzazione basata sui ruoli.

Per creare una classe che implementa ed estende IPrincipal

1.

Aggiungere una nuova classe denominata CustomPrincipal al progetto corrente.

2.

Aggiungere l'istruzione using riportata di seguito all'inizio di CustomPrincipal.cs.

using System.Security.Principal; 

3.

Derivare la classe CustomPrincipal dall'interfaccia IPrincipal.

public class CustomPrincipal : IPrincipal 

4.

Aggiungere le variabili membro private riportate di seguito alla classe per mantenere l'oggetto IIdentity associato all'oggetto Principal corrente e al relativo elenco dei ruoli.

private IIdentity _identity; 
private string [] _roles; 

5.

Modificare il costruttore predefinito della classe per accettare un oggetto IIdentity e la matrice dei ruoli. Utilizzare i valori specificati per inizializzare le variabili membro private come illustrato di seguito.

public CustomPrincipal(IIdentity identity, string [] roles) 
{ 
  _identity = identity; 
  _roles = new string[roles.Length]; 
  roles.CopyTo(_roles, 0); 
  Array.Sort(_roles); 
} 

6.

Implementare il metodo IsInRole e la proprietà Identity definita dall'interfaccia IPrincipal come illustrato di seguito.

// IPrincipal Implementation 
public bool IsInRole(string role) 
{ 
  return Array.BinarySearch( _roles, role ) >= 0 ? true : false; 
} 
public IIdentity Identity 
{ 
  get 
  { 
    return _identity; 
  } 
} 

7.

Aggiungere i due metodi pubblici riportati di seguito per fornire funzionalità estese di controllo dei ruoli.

// Checks whether a principal is in all of the specified set of roles 
public bool IsInAllRoles( params string [] roles ) 
{ 
  foreach (string searchrole in roles ) 
  { 
    if (Array.BinarySearch(_roles, searchrole) < 0 ) 
      return false; 
  } 
  return true; 
} 
// Checks whether a principal is in any of the specified set of roles 
public bool IsInAnyRoles( params string [] roles ) 
{ 
  foreach (string searchrole in roles ) 
  { 
    if (Array.BinarySearch(_roles, searchrole ) > 0 ) 
      return true; 
  } 
  return false; 
} 

Creazione dell'oggetto CustomPrincipal

Questa procedura consente di implementare un gestore eventi di autenticazione dell'applicazione e creare un oggetto CustomPrincipal per rappresentare l'utente autenticato in base alle informazioni contenute all'interno del ticket di autenticazione.

Per creare l'oggetto CustomPrincipal

1.

Da Esplora soluzioni aprire global.asax.

2.

Passare alla visualizzazione del codice, quindi aggiungere all'inizio del file le seguenti istruzioni using:

using System.Web.Security; 
using System.Security.Principal; 

3.

Individuare il gestore eventi Application_AuthenticateRequest e aggiungere il codice riportato di seguito per ottenere il cookie di autenticazione basata su moduli dall'insieme di cookie passato con la richiesta.

// Extract the forms authentication cookie 
string cookieName = FormsAuthentication.FormsCookieName; 
HttpCookie authCookie = Context.Request.Cookies[cookieName]; 
if(null == authCookie) 
{ 
  // There is no authentication cookie. 
  return; 
}  

4.

Aggiungere il codice riportato di seguito per estrarre il ticket di autenticazione dal cookie di autenticazione basata su moduli e decrittografarlo.

FormsAuthenticationTicket authTicket = null; 
try 
{ 
  authTicket = FormsAuthentication.Decrypt(authCookie.Value); 
} 
catch(Exception ex) 
{ 
  // Log exception details (omitted for simplicity) 
  return; 
} 
if (null == authTicket) 
{ 
  // Cookie failed to decrypt. 
  return;  
}  

5.

Aggiungere il codice riportato di seguito per analizzare l'elenco dei nomi dei ruoli separati da barre verticali associato al ticket quando l'utente è stato autenticato in origine.

// When the ticket was created, the UserData property was assigned a 
// pipe delimited string of role names. 
string[] roles = authTicket.UserData.Split('|'); 

6.

Aggiungere il codice riportato di seguito per creare un oggetto FormsIdentity con il nome utente ottenuto dal nome del ticket e un oggetto CustomPrincipal contenente l'identità stessa e il relativo elenco dei ruoli utente.

// Create an Identity object 
FormsIdentity id = new FormsIdentity( authTicket );  
// This principal will flow throughout the request. 
CustomPrincipal principal = new CustomPrincipal(id, roles); 
// Attach the new principal object to the current HttpContext object 
Context.User = principal; 

Test dell'applicazione

Questa procedura consente di aggiungere alla pagina default.aspx il codice per visualizzare informazioni dall'oggetto CustomPrincipal associato all'oggetto HttpContext corrente, in modo da verificare che l'oggetto sia stato creato e assegnato correttamente alla richiesta Web corrente. Consente inoltre di verificare la funzionalità basata sui ruoli supportata dalla nuova classe.

Per eseguire il test dell'applicazione

1.

In Esplora soluzioni fare doppio clic su default.aspx.

2.

Fare doppio clic sul modulo Web default.aspx per visualizzare il gestore eventi di caricamento della pagina.

3.

Scorrere verso l'inizio del file e aggiungere l'istruzione using riportata di seguito sotto le istruzioni using esistenti.

using System.Security.Principal; 

4.

Tornare al gestore eventi di caricamento della pagina e aggiungere il codice riportato di seguito per visualizzare il nome di identità correlato all'oggetto CustomPrincipal associato alla richiesta Web corrente.

CustomPrincipal cp = HttpContext.Current.User as CustomPrincipal; 
Response.Write( "Authenticated Identity is: " +   
                cp.Identity.Name ); 
Response.Write( "<p>" ); 

5.

Aggiungere il codice riportato di seguito per verificare l'appartenenza ai ruoli dell'identità autenticata corrente, utilizzando il metodo IsInRole standard e i metodi aggiuntivi IsInAnyRoles e IsInAllRoles supportati dalla classe CustomPrincipal.

if ( cp.IsInRole("Senior Manager") ) 
{ 
  Response.Write( cp.Identity.Name + " is in the " + "Senior Manager  
  Role" ); 
  Response.Write( "<p>" );             
} 
  if ( cp.IsInAnyRoles("Senior Manager", "Manager", "Employee", " 
  Sales") ) 
  { 
    Response.Write( cp.Identity.Name + " is in one of the specified  
    roles"); 
    Response.Write( "<p>" ); 
  } 
  if ( cp.IsInAllRoles("Senior Manager", "Manager", "Employee", " 
  Sales") ) 
  { 
    Response.Write( cp.Identity.Name + " is in ALL of the specified  
    roles" ); 
    Response.Write( "<p>" ); 
  } 
  else 
  { 
    Response.Write( cp.Identity.Name +  
                    " is not in ALL of the specified roles" ); 
    Response.Write("<p>"); 
  } 
  if ( cp.IsInRole("Sales") ) 
    Response.Write( "User is in Sales role<p>" ); 
  else 
    Response.Write( "User is not in Sales role<p>" ); 

6.

In Esplora soluzioni fare clic con il pulsante destro del mouse su default.aspx, quindi fare clic su Imposta come pagina iniziale.

7.

Scegliere Genera soluzione dal menu Genera.

8.

Premere CTRL+F5 per eseguire l'applicazione. Poiché default.aspx è configurata come pagina iniziale, questa è la pagina richiesta inizialmente.

9.

Quando si viene reindirizzati alla pagina di accesso poiché inizialmente non si dispone di un ticket di autenticazione, immettere un nome utente e una password qualsiasi, quindi fare clic su Accedi.

10.

Verificare che l'utente venga reindirizzato alla pagina default.aspx e che vengano visualizzati l'identità dell'utente e i dettagli corretti relativi ai ruoli. L'utente è un membro dei ruoli Senior Manager, Manager ed Employee ma non del ruolo Sales.

Altre risorse

Per ulteriori informazioni sull'autenticazione basata su moduli, vedere i seguenti moduli di questa guida:

"Procedura - Creazione di oggetti GenericPrincipal mediante l'autenticazione basata su moduli"

"Procedura - Utilizzo dell'autenticazione basata su moduli mediante Active Directory"

"Procedura - Utilizzo dell'autenticazione basata su moduli mediante SQL Server 2000"


**
In questo articolo
**