Forms Authentication: un'applicazione multi login

2 pagine in totale: <<Indietro 1 [2]

Abbiamo dotato la classe anche di una proprietà Settings che ci darà il riferimento alla sezione di configurazione nel web.config.

Implementiamo il metodo context_EndRequest come descritto precedentemente:

private void context_EndRequest(object sender, EventArgs e)
{
      HttpContext context = HttpContext.Current;
      // Controllo lo StatusCode
      if (context.Response.StatusCode == 401)
      {
        // Cerco il path nel config
        if (Settings.Page == null) return;
        string path = context.Request.PhysicalPath.ToLower();;
        foreach (PageLoginType page in Settings.Page)
        {
           string l = context.Server.MapPath(page.LoginUrl).ToLower();
           string p = context.Server.MapPath(page.Path).ToLower();
           // Se la pagina richiesta è nella lista di path
           if (p == path)
           {
              // Effettuo il redirect nuovo
              redirectToWithReturnUrl(page.LoginUrl, context);
              break;
           }
        }
      }
   }
   

Dopo aver verificato che non è stato dato il consenso alla pagina richiesta, dobbiamo controllare se è stato specificato per quel percorso una pagina login. Una volta trovato il path corretto effettuiamo il redirect che cambierà lo StatusCode a 302.

Il metodo redirectToWithReturnUrl non fa altro che prendere l'url di login, aggiungere il paramentro di querystring returnUrl con il path richiesto ed effettuare Response.Redirect. In questo modo il metodo FormsAuthentication.RedirectFromLoginPage, che utilizziamo normalmente per autenticare un utente, saprà dove rimandare l'utente una volta effettuato il login.

In un caso reale (come nell'esempio che è proposto in questo articolo) dovremmo usare questo modulo insieme all'autenticazione basata sui ruoli citata ad inizio articolo. Nella sezione authorization di un certo path o di una certa cartella, dovremmo dare accesso ad un certo ruolo e vietare l'accesso a tutti:

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

Nel caso in cui però vietiamo l'accesso anonimo a tutte le pagine (per questioni di comodità), si pone un problema: nel fare il redirect alla pagina di login specifica, non verrà dato l'accesso ad essa a meno che abbiamo specificato un sezione specializzata che ne autorizza gli accessi anonimi.

Guardando il codice di FormsAuthenticationModule si vede che ad inizio richiesta viene valorizzata la proprietà SkipAuthorization di HttpContext a seconda che la pagina richiesta sia la pagina di login o meno. Ecco il trucco, basta che anche noi impostiamo a true questa proprietà e il modulo UrlAuthorization salterà la fase di autorizzazione.

Gestiamo quindi l'evento AuthorizeRequest nella quale controlliamo la pagina richiesta con la lista delle pagine di login specifiche per indicare se saltare o meno l'autorizzazione:

   HttpContext context = HttpContext.Current;

   // Cerco il path nel config
   if (Settings.Page == null) return;
   string path = context.Request.PhysicalPath.ToLower();;
   foreach (PageLoginType page in Settings.Page)
   {
      string l = context.Server.MapPath(page.LoginUrl).ToLower();
      // Se il file richiesto è una delle pagine di login
      // allora faccio saltare l'autorizzazione al UrlAuthorizationModule
      if (l == path)
      {
        context.SkipAuthorization = true;
        break;
      }
   }

Probabilmente vi siete domandati, giustamente, perché AuthorizeRequest e non BeginRequest come evento. Prima non vi ho parlato di un problema che si presenta nell'utilizzo nel modulo. Per farlo lavorare dovremo inserire nel web.config:

<httpModules>
   <add name="MultiLogin" type="ASPItalia.com.Scripts.MultiLogin.MultiLoginModule, MultiLogin"/>
</httpModules>

Il motore di ASP.NET prende in ordine i moduli partendo dal machine.config fino ad arrivare al web.config, li istanzia e richiama il metodi Init uno per volta. Succede quindi che il metodo EndRequest del nostro modulo parta dopo quello di FormsAuthentication. Una bella grana, visto che in caso di errore 401 effettuerà il redirect prima di noi. Nessun problema, il trucchetto sta nel rimuovere il modulo FormsAuthentication per poi riaggiungerlo dopo il nostro. Si crea però un altro nuovo problema. Il nostro ipotetico BeginRequest partirà prima di quello del modulo Form e quest'ultimo valorizzerà SkipAuthorization e vanificherà il nostro lavoro. Ecco spiegato l'aver intercettato l'AuthorizeRequest. Non è ancora finita, l'UrlAuthorizationModule con il suo evento AutorizeRequest parte prima del nostro, quindi dobbiamo ripetere l'operazione anche questa volta.

La sezione httpModules del web.config definitiva sarà così:

<httpModules>
   <remove name="FormsAuthentication" />
   <remove name="UrlAuthorization" />
   <add name="MultiLogin" type="ASPItalia.com.Scripts.MultiLogin.MultiLoginModule, MultiLogin" />
   <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>
   <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
</httpModules>

Non è grave, se pensate che invece di mettere questa sezione inogni applicazione web, basta metterlo nel machine.config in modo da aggiungere questa funzionalità in modo definitivo.

Uso dell'esempio allegato

Provate ora l'esempio allegato. C'è una pagina default.aspx con accesso anonimo, che è collegata a 2 pagine: users.aspx e admin.aspx. La prima che permette l'accesso solo agli utenti di ruolo users e la seconda che dà accesso ad utenti con ruolo admin. Le pagine userslogin.aspx e adminlogin.aspx sono le due pagine di login personalizzate. Dal web.config (da notare la sezione personalizzata multiLogin) e dal global.asax vedrete che ho usato l'autenticazione a ruoli proposta ad inizio articolo.

Se cercate di entrare nella pagina di utenti, vi verrà proposto la pagina di loginusers.aspx, premete Entra (guardate il codice, non c'è nulla di nuovo) e verrete autenticati. Ora vi trovate in users.aspx. Tornate alla pagina principale e provate ad entrare nella pagina admin, vedrete che vi verrà proposto la pagina loginadmin.aspx, come volevamo.

Conclusioni

I moduli sono una caratteristica fondamentale di ASP.NET e ci permettono di riutilizzare codice con poche righe per dotare le nostre applicazioni di funzionalità aggiuntive. Consiglio infatti di usarli anche in altri ambiti come per esempio, nell'autenticazione a ruoli (invece di usare il global.asax) o nella gestione di errori non previsti (invio e-mail ecc).

Alcuni esempi li trovate a questo indirizzo .

Approfondimenti

2 pagine in totale: <<Indietro 1 [2]

Attenzione: Questo articolo contiene un allegato

Contenuti dell'articolo

Commenti
Dai un voto a questo articolo, ci aiuterà a migliorare il nostro sito (1 è il voto minimo, 5 il massimo).

Per procedere al rating dell'articolo devi essere autenticato.

Aggiungi un nuovo commento »»»
Per inserire un commento, devi registrarti alla nostra community.


TUTORIALS
TOP TEN ARTICOLI
NOTIFICHE

Iscriviti alla nostra newsletter nuoviarticoli per ricevere e-mail le notifiche!

Indirizzo e-mail:
PROVIDER ASP.NET 2.0

Seleziona il database per avere il web.config pronto per Membership, Roles e Profile API.



IN EVIDENZA
MISC