Oltre a limitare l'accesso ad alcune aree di una applicazione web, possiamo decidere di fornire ad alcuni utenti dei privilegi diversi all'interno dell'applicazione stessa, costituendo dei gruppi di utenti con ruoli differenti tra loro.
Pensiamo ad un giornale online, ovvero un sito per la gestione di contenuti. Per essere costantemente aggiornato con le ultime notizie, ha bisogno di diverse figure professionali. I giornalisti invece di scrivere su carta, scrivono direttamente sul sito. Ogni giornalista avrà a disposizione le sue pagine e sarà responsabile del loro contenuto. È chiaro che un giornalista non deve avere la possibilità di modificare le pagine assegnate agli altri.
Poi ci sarà una figura professionale che si occuperà della gestione dell'intero sito. In genere questa figura è chiamata amministratore. Questi avrà il compito di assegnare le pagine ai giornalisti e dovrà possedere maggiori privilegi del giornalista per accedere a delle parti del sito alle quali altri non possono accedere.
Quindi si capisce la necessità di assegnare ruoli diversi ai vari gruppi di utenti, con i relativi privilegi. In questo articolo vedremo come assegnare i ruoli agli utenti e come definire i privilegi di un ruolo sul file di configurazione del sito, il Web.config
.
Per assegnare i ruoli agli utenti, ASP.NET 2.0 mette a disposizione il WAT, cioè il tool di amministrazione del sito.
Possiamo anche creare la nostra pagina personalizzata per assegnare i ruoli scrivendo qualche riga di codice ed utilizzando la classe Roles
.
Vediamo con un esempio come utilizzare il WAT per definire i ruoli degli utenti. A tale scopo partiamo dall'esempio realizzato nell'articolo "Utilizzare il CreateUserWizard" che possiamo scaricare da qui e rinominare con nome "RuoliUtenti".
Il nome dell'applicazione (applicationName
) all'interno del Membership Provider
definito nel Web.config
, può rimanere invariato in modo da poter utilizzare i dati già inseriti. Se preferiamo usare il Membership Provider
di default, togliamo la sezione <membership>
dal Web.config
. In ogni caso, se non abbiamo i dati, creiamo con il WAT alcuni utenti come ad esempio quelli mostrati in figura:
Chi non sa utilizzare il WAT per inserire gli utenti, può riferirsi al capitolo Sicurezza della Guida ASP.NET 2.0.
Se nel nostro progetto abbiamo avviato il WAT e ci troviamo nella situazione visualizzata in figura 1, clicchiamo sul pulsante Indietro
in basso a destra.
Nel riquadro Ruoli
clicchiamo su Attiva ruoli
. Una volta abilitati i ruoli, clicchiamo su Crea o gestisci ruoli
. Appare un maschera in cui inserire il nome del ruolo che vogliamo creare. Inseriamo quindi un nome di ruolo per l'amministratore, ad esempio Admin
.
Clicchiamo quindi su Aggiungi Ruolo
. Il ruolo viene creato e visualizzato nella medesima pagina.
Per aggiungere un utente al ruolo Admin
clicchiamo sul link Gestisci
presente nella colonna Aggiungi/Rimuovi utenti
.
Mettiamo poi l'asterisco nel campo di ricerca per visualizzare tutti gli utenti. Quindi all'utente "Asdrubale" assegniamo il ruolo Admin
spuntando la casella corrispondente nella colonna Ruolo dell'utente
:
In questo modo Asdrubale diventa un membro del ruolo "Admin".
Ora, all'interno del nostro progetto, nella cartella "Inscritti", creiamo la cartella "Amministratore" ed all'interno di essa mettiamo un nuovo Web Form che possiamo chiamare DefaultAdmin.aspx
.
Per effettuare un test, mettiamo un'altra pagina nella cartella "Amministratore". Poi, per poter navigare da una pagina all'altra, mettiamo dei link fra le varie pagine e scriviamo qualcosa per riconoscerle.
All'interno della cartella "Amministratore" mettiamo anche un file di configurazione con una sezione <authorization>
.
Listato 1. Web.config della cartella Amministratore
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<authorization>
<allow roles="Admin"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
A questo punto possiamo fare un test per verificare che solo l'utente Asdrubale possa accedere alle pagine dell'amministratore.
La classe Roles
In questa parte dell'articolo vediamo come creare i ruoli ed assegnarli agli utenti senza usare il WAT ma utilizzando la classe Roles
.
Aggiungiamo un nuovo Web Form
alla cartella Amministratore
e chiamiamolo "Ruoli.aspx". e vi inseriamo una tabella come mostrato in figura.
La prima riga descrive il contenuto della seconda riga.
Nella seconda riga abbiamo una ListBox
per elencare i ruoli (ListBoxRuoli
), una ListBox
per elencare gli utenti (ListBoxUtenti
) che hanno il ruolo selezionato nella lista dei ruoli ed un'altra ListBox
per elencare gli utenti che invece non fanno parte del ruolo selezionato.
Le liste degli "Utenti nel ruolo" e quella degli "Utenti fuori" serviranno anche ad assegnare o a togliere agli utenti il ruolo selezionato.
Nella quarta riga della tabella abbiamo una casella di testo per inserire il nome di un nuovo ruolo (TextBoxNewRuolo
) ed un pulsante per inserire il ruolo nel database (ButtonAddRuolo
).
Nell'ultima riga della tabella abbiamo una checklist (CheckBoxListRuoli
) per elencare i ruoli, con la possibilità di selezionarne uno o più di uno per la cancellazione dal database, che avverrà cliccando sul pulsante Conferma cancellazione (ButtonDelete
).
È inoltre presente un'etichetta in rosso per visualizzare eventuali messaggi.
Definita l'interfaccia utente dobbiamo implementare i metodi che gestiscono la visualizzazione, l'inserimento e la cancellazione dei ruoli nonché la gestione degli utenti appartenenti ai ruoli, quindi implementare anche l'inserimento e l'eliminazione degli utenti dai ruoli.
Cominciamo ad implementare il metodo per popolare la ListBoxRuoli
e la CheckBoxListRuoli
.
Listato 2. PopolamentoListeRuoli()
protected void PopolamentoListeRuoli()
{
string[] ruoli;
ruoli = Roles.GetAllRoles();
ListBoxRuoli.Items.Clear();
CheckBoxListRuoli.Items.Clear();
for (int i = 0; i < ruoli.Length; i++)
{
ListBoxRuoli.Items.Add(ruoli[i].ToString());
CheckBoxListRuoli.Items.Add(ruoli[i].ToString());
}
}
Questo metodo parte con la definizione di un array di stringhe (ruoli
), che servirà da contenitore per i nomi dei ruoli presenti nel database, ed utilizza il metodo GetAllRoles()
della classe Roles
, per riempire l'array. Il resto del codice serve a cancellare le due liste, per popolarle nuovamente con dati aggiornati.
Implementiamo adesso il metodo per popolare le liste degli utenti.
Listato 3. PopolamentoListeUtenti()
protected void PopolamentoListeUtenti()
{
ListBoxUtenti.Items.Clear();
if (ListBoxRuoli.SelectedItem != null)
{
string[] utentiInRuolo = Roles.GetUsersInRole(ListBoxRuoli.SelectedItem.ToString());
for (int i = 0; i < utentiInRuolo.Length; i++)
ListBoxUtenti.Items.Add(utentiInRuolo[i].ToString());
// popolamento lista ListBoxUtentiNon
ListBoxUtentiNon.Items.Clear();
MembershipUserCollection utenti = Membership.GetAllUsers();
foreach (MembershipUser UserName in utenti)
if (!Roles.IsUserInRole(UserName.ToString(), ListBoxRuoli.SelectedItem.ToString()))
ListBoxUtentiNon.Items.Add(UserName.ToString());
}
}
Questo metodo cancella i dati della ListBoxUtenti
, controlla poi che ci sia un elemento selezionato sulla ListBoxRuoli
perché è da questo dato che si estraggono le due liste.
Riempie poi l'array di stringhe utentiInRuolo
utilizzando il metodo GetUsersInRole
della classe Roles
. Il metodo GetUsersInRole
prende in input il nome del ruolo e restituisce tutti gli utenti che ne fanno parte.
Per popolare la seconda lista dobbiamo prendere tutti gli utenti che non fanno parte di quel ruolo. Estraiamo quindi la Collection utenti
dal database per mezzo del metodo GetAllUsers()
della classe Membership
. Per ogni utente estratto, controlliamo che non faccia parte del ruolo per mezzo del metodo IsUserInRole
e quindi popoliamo la lista. IsUserInRole
, usato con due parametri, il nome utente ed il ruolo, ci restituisce un valore booleano che è true
se l'utente appartiene al ruolo.
Gestione dei pulsanti.
Nell'interfaccia utente abbiamo la TextBox TextBoxNewRuolo
che serve ad inserire un ruolo nel database mediante immissione del suo nome che lo identificherà univocamente.
Una volta inserito il nome del nuovo ruolo nella TextBoxNewRuolo
, cliccando sul pulsante ButtonAddRuolo
il nuovo ruolo viene aggiunto.
Dobbiamo quindi implementare il gestore dell'evento OnClick
sul pulsante ButtonAddRuolo
.
Listato 4. Gestore dell'evento OnClick sul pulsante ButtonAddRuolo
protected void ButtonAddRuolo_Click(object sender, EventArgs e)
{
if (!Roles.RoleExists(TextBoxNewRuolo.Text))
{
Roles.CreateRole(TextBoxNewRuolo.Text);
ListBoxRuoli.Items.Add(TextBoxNewRuolo.Text);
CheckBoxListRuoli.Items.Add(TextBoxNewRuolo.Text);
}
else
LabelMsg.Text= "Ruolo " + TextBoxNewRuolo.Text + " già esistente";
}
Questo metodo verifica l'esistenza del ruolo che si vuole inserire. Infatti non si possono inserire due ruoli con lo stesso nome, se provassimo a farlo, il Membership Provider
solleverebbe un'eccezione.
La creazione del nuovo ruolo avviene mediante la chiamata del metodo CreateRole
della classe Roles
, cui passiamo il nome del nuovo ruolo. Se il ruolo già esiste mandiamo un messaggio all'amministratore.
L'altra cosa che dobbiamo fare è aggiungere il nuovo ruolo alla due liste dei ruoli presenti nell'interfaccia utente: la ListBoxRuoli
e la CheckBoxListRuoli
.
Il ButtonDelete
serve a cancellare il ruolo spuntato nella CheckBoxListRuoli
. Implementiamo il gestore del click sul ButtonDelete
.
Listato 5. Gestore dell'evento OnClick sul pulsante ButtonDelete
protected void ButtonDelete_Click(object sender, EventArgs e)
{
for (int i = 0; i < CheckBoxListRuoli.Items.Count; i++)
if (CheckBoxListRuoli.Items[i].Selected)
{
Roles.RemoveUsersFromRole(Roles.GetUsersInRole(CheckBoxListRuoli.Items[i].Text),
CheckBoxListRuoli.Items[i].Text);
Roles.DeleteRole(CheckBoxListRuoli.Items[i].Text);
}
PopolamentoListeRuoli();
PopolamentoListeUtenti();
}
Il ButtonDelete_Click
prende l'elemento (o gli elementi) selezionato nella checklist e, prima rimuove tutti gli utenti dal ruolo che si vuole cancellare mediante il metodo RemoveUsersFromRole
, e poi, cancella il ruolo per mezzo del metodo DeleteRole
. È necessario togliere prima tutti gli utenti perché non si può cancellare un ruolo che non sia vuoto.
Infine il ButtonDelete_Click
ripopola le liste dei ruoli e degli utenti prive del ruolo cancellato.
Page_Load
Listato 6. Implementazione del Page_Load
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
PopolamentoListeRuoli(); // popolamento liste ruoli
PopolamentoListeUtenti(); // popolamento lista utenti in ruolo
}
Il Page_Load
si occupa solo di chiamare i metodi per popolare le liste che abbiamo già esaminato.
Affinché il tutto funzioni, dobbiamo anche implementare il gestore dell'evento Page_PreLoad
che viene lanciato con il vecchio view state
.
Listato 7. Implementazione del Page_PreLoad
protected void Page_PreLoad(object sender, EventArgs e)
{
if (ListBoxUtentiNon.SelectedItem != null)
Roles.AddUserToRole(ListBoxUtentiNon.SelectedValue, ListBoxRuoli.SelectedValue);
if (ListBoxUtenti.SelectedItem != null)
Roles.RemoveUserFromRole(ListBoxUtenti.SelectedValue, ListBoxRuoli.SelectedValue);
}
L'esigenza di usare il Page_PreLoad
nasce dal fatto che quando vogliamo ad esempio aggiungere un utente ad un ruolo, dobbiamo prelevarlo dalla ListBoxUtentiNon
ed al prossimo PostBack
visualizzarlo nella lista ListBoxUtenti
. Queste due liste sono però popolate partendo dal ruolo selezionato nella lista ListBoxRuoli
che non appena avviene il PostBack
ripopola le due liste facendo perdere il SelectedValue
precedente.
Durante l'esecuzione di Page_PreLoad
abbiamo ancora a disposizione il valore selezionato ed il ripopolamento avviene successivamente nel Page_Load
.
Inoltre, nelle liste ListBoxRuoli
, ListBoxUtenti
e ListBoxUtentiNon
, dobbiamo impostiare la proprietà: AutoPostBack="True"
.
A questo punto possiamo testare la nostra pagina Ruoli.aspx
e verificare che il tutto funzioni.
Entriamo come Admin
, cioè con l'utente Asdrubale. Selezionando il ruolo Admin
sulla prima lista ci troviamo nella seguente situazione:
L'applicazione riconosce un solo ruolo Admin
assegnato solo all'utente "Asdrubale". Gli altri utenti sono visualizzati nella lista degli Utenti fuori.
Aggiungiamo un nuovo ruolo specificando un nome diverso da Admin
. Ad esempio Risorse
e lo assegnamo agli utenti Pippo e Pluto. Per farlo selezioniamo Risorse
sulla lista dei Ruoli e poi Pippo e Pluto sulla lista degli Utenti fuori. Appena selezionato, un utente passa da una lista all'altra.
Alla fine di questa operazione lo scenario diventa il seguente:
Anche la lista Cancella ruoli si è aggiornata.
Proviamo ora ad aggiungere NonnaPapera a Risorse
e poi a toglierla per verificare che funziona anche il passaggio inverso.
Verifichiamo che aggiungendo di nuovo il ruolo Risorse
ci ritorna un messaggio di errore. Verifichiamo poi anche la cancellazione di un ruolo.
L'esempio sviluppato in questo articolo, privato del database per comodità, può essere scaricato da qui.